{"version":3,"file":"rounding.cjs","names":["sum"],"sources":["../../../src/common/data/rounding.ts"],"sourcesContent":["// From https://v2.dinerojs.com/docs/api/formatting/to-unit MIT\n\nimport { sum } from './math'\n\nexport type RoundingMode = (value: number) => number\n\nexport function isHalf(value: number): boolean {\n  return Math.abs(value) % 1 === 0.5\n}\nexport function isEven(value: number): boolean {\n  return value % 2 === 0\n}\n\nexport const roundUp: RoundingMode = value => Math.ceil(value)\nexport const roundDown: RoundingMode = value => Math.floor(value)\nexport const roundHalfUp: RoundingMode = value => Math.round(value)\n\n/**\n * Round a number with half values to nearest odd integer.\n */\nexport const roundHalfOdd: RoundingMode = (value) => {\n  const rounded = Math.round(value)\n  if (!isHalf(value))\n    return rounded\n\n  return isEven(rounded) ? rounded - 1 : rounded\n}\n\n/**\n * Round a number with half values to nearest integer farthest from zero.\n */\nexport const roundHalfAwayFromZero: RoundingMode = (value) => {\n  return isHalf(value)\n    ? Math.sign(value) * Math.ceil(Math.abs(value))\n    : Math.round(value)\n}\n\n/**\n * Round a number with half values down.\n */\nexport const roundHalfDown: RoundingMode = value =>\n  isHalf(value) ? Math.floor(value) : Math.round(value)\n\n/**\n * Round a number with half values to nearest even integer.\n * https://wiki.c2.com/?BankersRounding\n */\nexport const roundHalfEven: RoundingMode = (value) => {\n  const rounded = Math.round(value)\n  if (!isHalf(value))\n    return rounded\n\n  return isEven(rounded) ? rounded : rounded - 1\n}\n\n/**\n * Round a number with half values to nearest integer closest to zero.\n */\nexport const roundHalfTowardsZero: RoundingMode = value =>\n  isHalf(value)\n    ? Math.sign(value) * Math.floor(Math.abs(value))\n    : Math.round(value)\n\n/**\n * This is useful for percentages that should sum up to 100.\n * But can also be fine tuned.\n *\n * Original from https://github.com/super-ienien/percent-round\n */\nexport function roundArrayOfNumbersToMatchSum(ipt: number[], max = 100, decimalPlaces = 0) {\n  const iptPercents: number[] = [...ipt]\n  const length = ipt.length\n  const out: number[] = []\n  out.fill(0, length)\n\n  const total = sum(iptPercents)\n\n  if (total !== 0) {\n    const powDecimalPlaces = 10 ** decimalPlaces\n    const pow100 = max * powDecimalPlaces\n    let check100 = 0\n    for (let i = length - 1; i >= 0; i--) {\n      iptPercents[i] = max * iptPercents[i] / total\n      check100 += out[i] = Math.round(iptPercents[i] * powDecimalPlaces)\n    }\n\n    if (check100 !== pow100) {\n      const totalDiff = (check100 - pow100)\n      const roundGrain = 1\n      let grainCount = Math.abs(totalDiff)\n      const diffs = iptPercents.map((_, i) => Math.abs(out[i] - iptPercents[i] * powDecimalPlaces))\n\n      while (grainCount > 0) {\n        let idx = 0\n        let maxDiff = diffs[0]\n        for (let i = 1; i < length; i++) {\n          if (maxDiff < diffs[i]) {\n            // avoid negative result\n            if (check100 > pow100 && out[i] - roundGrain < 0)\n              continue\n            idx = i\n            maxDiff = diffs[i]\n          }\n        }\n        if (check100 > pow100)\n          out[idx] -= roundGrain\n        else\n          out[idx] += roundGrain\n\n        diffs[idx] -= roundGrain\n        grainCount--\n      }\n    }\n\n    if (powDecimalPlaces > 1)\n      return out.map(n => +((n / powDecimalPlaces).toFixed(decimalPlaces)))\n  }\n\n  return out\n}\n\nexport function roundArrayOfObjectsToMatchSum<T extends Record<string, any>>(arr: T[], name: string, max = 100, decimalPlaces = 0): T[] {\n  return roundArrayOfNumbersToMatchSum(arr.map(o => o[name]), max, decimalPlaces)\n    .map((o, i) => ({\n      ...arr[i],\n      [name]: o,\n    }))\n}\n"],"mappings":";;;;AAMA,SAAgB,OAAO,OAAwB;AAC7C,QAAO,KAAK,IAAI,MAAM,GAAG,MAAM;;AAEjC,SAAgB,OAAO,OAAwB;AAC7C,QAAO,QAAQ,MAAM;;AAGvB,MAAa,WAAwB,UAAS,KAAK,KAAK,MAAM;AAC9D,MAAa,aAA0B,UAAS,KAAK,MAAM,MAAM;AACjE,MAAa,eAA4B,UAAS,KAAK,MAAM,MAAM;;;;AAKnE,MAAa,gBAA8B,UAAU;CACnD,MAAM,UAAU,KAAK,MAAM,MAAM;AACjC,KAAI,CAAC,OAAO,MAAM,CAChB,QAAO;AAET,QAAO,OAAO,QAAQ,GAAG,UAAU,IAAI;;;;;AAMzC,MAAa,yBAAuC,UAAU;AAC5D,QAAO,OAAO,MAAM,GAChB,KAAK,KAAK,MAAM,GAAG,KAAK,KAAK,KAAK,IAAI,MAAM,CAAC,GAC7C,KAAK,MAAM,MAAM;;;;;AAMvB,MAAa,iBAA8B,UACzC,OAAO,MAAM,GAAG,KAAK,MAAM,MAAM,GAAG,KAAK,MAAM,MAAM;;;;;AAMvD,MAAa,iBAA+B,UAAU;CACpD,MAAM,UAAU,KAAK,MAAM,MAAM;AACjC,KAAI,CAAC,OAAO,MAAM,CAChB,QAAO;AAET,QAAO,OAAO,QAAQ,GAAG,UAAU,UAAU;;;;;AAM/C,MAAa,wBAAqC,UAChD,OAAO,MAAM,GACT,KAAK,KAAK,MAAM,GAAG,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,GAC9C,KAAK,MAAM,MAAM;;;;;;;AAQvB,SAAgB,8BAA8B,KAAe,MAAM,KAAK,gBAAgB,GAAG;CACzF,MAAM,cAAwB,CAAC,GAAG,IAAI;CACtC,MAAM,SAAS,IAAI;CACnB,MAAM,MAAgB,EAAE;AACxB,KAAI,KAAK,GAAG,OAAO;CAEnB,MAAM,QAAQA,6BAAI,YAAY;AAE9B,KAAI,UAAU,GAAG;EACf,MAAM,mBAAmB,MAAM;EAC/B,MAAM,SAAS,MAAM;EACrB,IAAI,WAAW;AACf,OAAK,IAAI,IAAI,SAAS,GAAG,KAAK,GAAG,KAAK;AACpC,eAAY,KAAK,MAAM,YAAY,KAAK;AACxC,eAAY,IAAI,KAAK,KAAK,MAAM,YAAY,KAAK,iBAAiB;;AAGpE,MAAI,aAAa,QAAQ;GACvB,MAAM,YAAa,WAAW;GAC9B,MAAM,aAAa;GACnB,IAAI,aAAa,KAAK,IAAI,UAAU;GACpC,MAAM,QAAQ,YAAY,KAAK,GAAG,MAAM,KAAK,IAAI,IAAI,KAAK,YAAY,KAAK,iBAAiB,CAAC;AAE7F,UAAO,aAAa,GAAG;IACrB,IAAI,MAAM;IACV,IAAI,UAAU,MAAM;AACpB,SAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,IAC1B,KAAI,UAAU,MAAM,IAAI;AAEtB,SAAI,WAAW,UAAU,IAAI,KAAK,aAAa,EAC7C;AACF,WAAM;AACN,eAAU,MAAM;;AAGpB,QAAI,WAAW,OACb,KAAI,QAAQ;QAEZ,KAAI,QAAQ;AAEd,UAAM,QAAQ;AACd;;;AAIJ,MAAI,mBAAmB,EACrB,QAAO,IAAI,KAAI,MAAK,EAAG,IAAI,kBAAkB,QAAQ,cAAc,CAAE;;AAGzE,QAAO;;AAGT,SAAgB,8BAA6D,KAAU,MAAc,MAAM,KAAK,gBAAgB,GAAQ;AACtI,QAAO,8BAA8B,IAAI,KAAI,MAAK,EAAE,MAAM,EAAE,KAAK,cAAc,CAC5E,KAAK,GAAG,OAAO;EACd,GAAG,IAAI;GACN,OAAO;EACT,EAAE"}