/* eslint-disable no-param-reassign */
/* eslint-disable no-restricted-globals */
// 判断传入的是否是数字或者可转为数字的字符串
export const isNumber = (value: string | number): boolean => {
  return /^(-|\+)?\d+(\.\d+)?$/.test(value as string);
};

export const innerRound = (num: number, length: number, decimal: number): number => {
  let value;
  let pre = 1;
  if (length === 0) return num;
  if (num < 0) pre = -1; // 负数的时候先变成正数
  num *= pre;
  const n = 10 ** length;
  value = Math.round(num * n);
  if (length <= decimal) {
    return (value / n) * pre;
  }
  value = Math.round(value / 10 ** (length - decimal));
  return (value / 10 ** decimal) * pre;
};

// 4舍5入
export const roundForObj = (obj: string | number | undefined | null, decimal: number): number => {
  let value;
  if (obj === undefined || obj === null || isNaN(obj as number)) return 0;
  const length = 10;
  if (obj === +obj) {
    value = innerRound(obj, length, decimal);
  } else {
    value = innerRound(Number(obj), length, decimal);
  }
  return value;
};

export const roundToString = (obj: string | number, decimal: number): string => {
  const value = roundForObj(obj, decimal);
  return value.toFixed(decimal);
};

const getTimesFromStr = (str: string) => {
  const reg = new RegExp('^[0-9]+');
  if (str && reg.test(str)) {
    const arr: any = str.match(reg);
    return parseInt(arr[0], 10);
  }
  return 1;
};

// 取单位前的数字，并转换成整数
export const getNumberFromUnit = (unit: string): number => {
  if (unit.indexOf('·') !== -1) {
    // 处理单位为 100m2·10天 的情况
    const strArr = unit.split('·');
    let time = 1;
    for (const s of strArr) {
      time *= getTimesFromStr(s);
    }
    return time;
  }
  return getTimesFromStr(unit);
};

// 返回平均值，标准差
export const standardDeviation = (arr: number[]) => {
  if (arr.length === 0) return { avg: 0, stdDev: 0 };

  const avg = arr.reduce((acc, val) => acc + val, 0) / arr.length;

  const stdDev = Math.sqrt(
    arr.reduce((acc: number[], val) => acc.concat((val - avg) ** 2), []).reduce((acc, val) => acc + val, 0) / arr.length
  );

  return { avg, stdDev };
};

// 是否在三倍标准差内  true 则为有效数值
export const isValidVal = (value: number, avg: number, stdDev: number) => {
  return Math.abs(value - avg) <= 3 * stdDev;
};

// 用三倍标准差法过滤无效数据
export const filterByStdDev = (arr: number[]) => {
  const { avg, stdDev } = standardDeviation(arr);

  return arr.filter(n => isValidVal(n, avg, stdDev));
};
