about summary refs log tree commit diff
path: root/app/javascript/flavours/glitch/util/numbers.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/javascript/flavours/glitch/util/numbers.js')
-rw-r--r--app/javascript/flavours/glitch/util/numbers.js71
1 files changed, 71 insertions, 0 deletions
diff --git a/app/javascript/flavours/glitch/util/numbers.js b/app/javascript/flavours/glitch/util/numbers.js
new file mode 100644
index 000000000..6f2505cae
--- /dev/null
+++ b/app/javascript/flavours/glitch/util/numbers.js
@@ -0,0 +1,71 @@
+// @ts-check
+
+export const DECIMAL_UNITS = Object.freeze({
+  ONE: 1,
+  TEN: 10,
+  HUNDRED: Math.pow(10, 2),
+  THOUSAND: Math.pow(10, 3),
+  MILLION: Math.pow(10, 6),
+  BILLION: Math.pow(10, 9),
+  TRILLION: Math.pow(10, 12),
+});
+
+const TEN_THOUSAND = DECIMAL_UNITS.THOUSAND * 10;
+const TEN_MILLIONS = DECIMAL_UNITS.MILLION * 10;
+
+/**
+ * @typedef {[number, number, number]} ShortNumber
+ * Array of: shorten number, unit of shorten number and maximum fraction digits
+ */
+
+/**
+ * @param {number} sourceNumber Number to convert to short number
+ * @returns {ShortNumber} Calculated short number
+ * @example
+ * shortNumber(5936);
+ * // => [5.936, 1000, 1]
+ */
+export function toShortNumber(sourceNumber) {
+  if (sourceNumber < DECIMAL_UNITS.THOUSAND) {
+    return [sourceNumber, DECIMAL_UNITS.ONE, 0];
+  } else if (sourceNumber < DECIMAL_UNITS.MILLION) {
+    return [
+      sourceNumber / DECIMAL_UNITS.THOUSAND,
+      DECIMAL_UNITS.THOUSAND,
+      sourceNumber < TEN_THOUSAND ? 1 : 0,
+    ];
+  } else if (sourceNumber < DECIMAL_UNITS.BILLION) {
+    return [
+      sourceNumber / DECIMAL_UNITS.MILLION,
+      DECIMAL_UNITS.MILLION,
+      sourceNumber < TEN_MILLIONS ? 1 : 0,
+    ];
+  } else if (sourceNumber < DECIMAL_UNITS.TRILLION) {
+    return [
+      sourceNumber / DECIMAL_UNITS.BILLION,
+      DECIMAL_UNITS.BILLION,
+      0,
+    ];
+  }
+
+  return [sourceNumber, DECIMAL_UNITS.ONE, 0];
+}
+
+/**
+ * @param {number} sourceNumber Original number that is shortened
+ * @param {number} division The scale in which short number is displayed
+ * @returns {number} Number that can be used for plurals when short form used
+ * @example
+ * pluralReady(1793, DECIMAL_UNITS.THOUSAND)
+ * // => 1790
+ */
+export function pluralReady(sourceNumber, division) {
+  // eslint-disable-next-line eqeqeq
+  if (division == null || division < DECIMAL_UNITS.HUNDRED) {
+    return sourceNumber;
+  }
+
+  let closestScale = division / DECIMAL_UNITS.TEN;
+
+  return Math.trunc(sourceNumber / closestScale) * closestScale;
+}