2021-09-05 01:09:30 +02:00
|
|
|
import numeral from "numeral";
|
|
|
|
import "numeral/locales/bg";
|
|
|
|
import "numeral/locales/cs";
|
|
|
|
import "numeral/locales/da-dk";
|
|
|
|
import "numeral/locales/de";
|
|
|
|
import "numeral/locales/en-au";
|
|
|
|
import "numeral/locales/en-gb";
|
|
|
|
import "numeral/locales/es";
|
|
|
|
import "numeral/locales/fr";
|
|
|
|
import "numeral/locales/hu";
|
|
|
|
import "numeral/locales/it";
|
|
|
|
import "numeral/locales/lv";
|
|
|
|
import "numeral/locales/no";
|
|
|
|
import "numeral/locales/pl";
|
|
|
|
import "numeral/locales/ru";
|
2018-09-12 17:53:08 +02:00
|
|
|
|
2021-12-30 00:51:59 +01:00
|
|
|
import { Settings } from "../Settings/Settings";
|
|
|
|
|
2021-06-02 22:07:52 +02:00
|
|
|
const extraFormats = [1e15, 1e18, 1e21, 1e24, 1e27, 1e30];
|
2021-09-05 01:09:30 +02:00
|
|
|
const extraNotations = ["q", "Q", "s", "S", "o", "n"];
|
2021-12-30 00:51:59 +01:00
|
|
|
const gigaMultiplier = { standard: 1e9, iec60027_2: 2 ** 30 };
|
2021-06-03 03:33:27 +02:00
|
|
|
|
2018-09-12 17:53:08 +02:00
|
|
|
class NumeralFormatter {
|
2021-09-05 01:09:30 +02:00
|
|
|
// Default Locale
|
|
|
|
defaultLocale = "en";
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
this.defaultLocale = "en";
|
|
|
|
}
|
|
|
|
|
|
|
|
updateLocale(l: string): boolean {
|
|
|
|
if (numeral.locale(l) == null) {
|
|
|
|
console.warn(`Invalid locale for numeral: ${l}`);
|
|
|
|
|
|
|
|
numeral.locale(this.defaultLocale);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
format(n: number, format: string): string {
|
|
|
|
// numeraljs doesnt properly format numbers that are too big or too small
|
|
|
|
if (Math.abs(n) < 1e-6) {
|
|
|
|
n = 0;
|
|
|
|
}
|
|
|
|
const answer = numeral(n).format(format);
|
|
|
|
if (answer === "NaN") {
|
|
|
|
return `${n}`;
|
|
|
|
}
|
|
|
|
return answer;
|
|
|
|
}
|
|
|
|
|
|
|
|
formatBigNumber(n: number): string {
|
2022-03-29 21:33:22 +02:00
|
|
|
return this.format(n, "0.000a");
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: leverage numeral.js to do it. This function also implies you can
|
|
|
|
// use this format in some text field but you can't. ( "1t" will parse but
|
|
|
|
// "1s" will not)
|
|
|
|
formatReallyBigNumber(n: number, decimalPlaces = 3): string {
|
2022-03-17 12:47:27 +01:00
|
|
|
const nAbs = Math.abs(n);
|
2021-09-05 01:09:30 +02:00
|
|
|
if (n === Infinity) return "∞";
|
|
|
|
for (let i = 0; i < extraFormats.length; i++) {
|
2022-03-17 12:47:27 +01:00
|
|
|
if (extraFormats[i] < nAbs && nAbs <= extraFormats[i] * 1000) {
|
2021-09-09 05:47:34 +02:00
|
|
|
return this.format(n / extraFormats[i], "0." + "0".repeat(decimalPlaces)) + extraNotations[i];
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
}
|
2022-03-17 12:47:27 +01:00
|
|
|
if (nAbs < 1000) {
|
2022-03-29 21:33:22 +02:00
|
|
|
return this.format(n, "0." + "0".repeat(decimalPlaces));
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2022-03-29 21:33:22 +02:00
|
|
|
const str = this.format(n, "0." + "0".repeat(decimalPlaces) + "a");
|
|
|
|
if (str === "NaNt") return this.format(n, "0." + " ".repeat(decimalPlaces) + "e+0");
|
2021-09-05 01:09:30 +02:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
formatHp(n: number): string {
|
|
|
|
if (n < 1e6) {
|
|
|
|
return this.format(n, "0,0");
|
|
|
|
}
|
|
|
|
return this.formatReallyBigNumber(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
formatMoney(n: number): string {
|
|
|
|
return "$" + this.formatReallyBigNumber(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
formatSkill(n: number): string {
|
|
|
|
if (n < 1e15) {
|
|
|
|
return this.format(n, "0,0");
|
|
|
|
}
|
|
|
|
return this.formatReallyBigNumber(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
formatExp(n: number): string {
|
|
|
|
return this.formatReallyBigNumber(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
formatHashes(n: number): string {
|
|
|
|
return this.formatReallyBigNumber(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
formatReputation(n: number): string {
|
|
|
|
return this.formatReallyBigNumber(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
formatFavor(n: number): string {
|
|
|
|
return this.format(n, "0,0");
|
|
|
|
}
|
|
|
|
|
2021-12-20 20:13:56 +01:00
|
|
|
formatSecurity(n: number): string {
|
|
|
|
return n.toFixed(3);
|
|
|
|
}
|
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
formatRAM(n: number): string {
|
2022-03-29 21:33:22 +02:00
|
|
|
if (Settings.UseIEC60027_2) {
|
2021-12-30 00:51:59 +01:00
|
|
|
return this.format(n * gigaMultiplier.iec60027_2, "0.00ib");
|
|
|
|
}
|
|
|
|
return this.format(n * gigaMultiplier.standard, "0.00b");
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
formatPercentage(n: number, decimalPlaces = 2): string {
|
|
|
|
const formatter: string = "0." + "0".repeat(decimalPlaces) + "%";
|
|
|
|
return this.format(n, formatter);
|
|
|
|
}
|
|
|
|
|
|
|
|
formatServerSecurity(n: number): string {
|
|
|
|
return this.format(n, "0,0.000");
|
|
|
|
}
|
|
|
|
|
|
|
|
formatRespect(n: number): string {
|
|
|
|
return this.formatReallyBigNumber(n, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
formatWanted(n: number): string {
|
|
|
|
return this.formatReallyBigNumber(n, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
formatMultiplier(n: number): string {
|
|
|
|
return this.format(n, "0,0.00");
|
|
|
|
}
|
|
|
|
|
|
|
|
formatSleeveShock(n: number): string {
|
|
|
|
return this.format(n, "0,0.000");
|
|
|
|
}
|
|
|
|
|
|
|
|
formatSleeveSynchro(n: number): string {
|
|
|
|
return this.format(n, "0,0.000");
|
|
|
|
}
|
|
|
|
|
|
|
|
formatSleeveMemory(n: number): string {
|
|
|
|
return this.format(n, "0");
|
|
|
|
}
|
|
|
|
|
|
|
|
formatPopulation(n: number): string {
|
|
|
|
return this.format(n, "0.000a");
|
|
|
|
}
|
|
|
|
|
|
|
|
formatStamina(n: number): string {
|
|
|
|
return this.format(n, "0.0");
|
|
|
|
}
|
|
|
|
|
|
|
|
formatShares(n: number): string {
|
|
|
|
if (n < 1000) {
|
|
|
|
return this.format(n, "0");
|
|
|
|
}
|
|
|
|
return this.formatReallyBigNumber(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
formatInfiltrationSecurity(n: number): string {
|
|
|
|
return this.formatReallyBigNumber(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
formatThreads(n: number): string {
|
|
|
|
return this.format(n, "0,0");
|
|
|
|
}
|
|
|
|
|
2021-09-25 23:21:50 +02:00
|
|
|
formatStaneksGiftHeat(n: number): string {
|
|
|
|
return this.format(n, "0.000a");
|
|
|
|
}
|
|
|
|
|
|
|
|
formatStaneksGiftCharge(n: number): string {
|
|
|
|
return this.format(n, "0.000a");
|
|
|
|
}
|
|
|
|
|
|
|
|
formatStaneksGiftPower(n: number): string {
|
2021-10-07 07:36:59 +02:00
|
|
|
return this.format(n, "0.00");
|
2021-09-25 23:21:50 +02:00
|
|
|
}
|
|
|
|
|
2022-03-17 12:47:27 +01:00
|
|
|
parseCustomLargeNumber(str: string): number {
|
2022-03-29 21:33:22 +02:00
|
|
|
const numericRegExp = new RegExp("^(-?\\d+\\.?\\d*)([" + extraNotations.join("") + "]?)$");
|
2022-03-17 12:47:27 +01:00
|
|
|
const match = str.match(numericRegExp);
|
|
|
|
if (match == null) {
|
|
|
|
return NaN;
|
|
|
|
}
|
|
|
|
const [, number, notation] = match;
|
|
|
|
const notationIndex = extraNotations.indexOf(notation);
|
|
|
|
if (notationIndex === -1) {
|
|
|
|
return NaN;
|
|
|
|
}
|
|
|
|
return parseFloat(number) * extraFormats[notationIndex];
|
|
|
|
}
|
|
|
|
|
2022-03-18 13:03:13 +01:00
|
|
|
largestAbsoluteNumber(n1: number, n2 = 0, n3 = 0): number {
|
2022-03-29 21:33:22 +02:00
|
|
|
if (isNaN(n1)) n1 = 0;
|
|
|
|
if (isNaN(n2)) n2 = 0;
|
|
|
|
if (isNaN(n3)) n3 = 0;
|
2022-03-18 13:03:13 +01:00
|
|
|
const largestAbsolute = Math.max(Math.abs(n1), Math.abs(n2), Math.abs(n3));
|
2022-03-29 21:33:22 +02:00
|
|
|
switch (largestAbsolute) {
|
|
|
|
case Math.abs(n1):
|
|
|
|
return n1;
|
|
|
|
case Math.abs(n2):
|
|
|
|
return n2;
|
|
|
|
case Math.abs(n3):
|
|
|
|
return n3;
|
2022-03-17 12:47:27 +01:00
|
|
|
}
|
2022-03-18 09:30:25 +01:00
|
|
|
return 0;
|
2022-03-17 12:47:27 +01:00
|
|
|
}
|
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
parseMoney(s: string): number {
|
2022-03-17 12:47:27 +01:00
|
|
|
// numeral library does not handle formats like 1s (returns 1) and 1e10 (returns 110) well,
|
|
|
|
// so if more then 1 return a valid number, return the one farthest from 0
|
2021-09-05 01:09:30 +02:00
|
|
|
const numeralValue = numeral(s).value();
|
|
|
|
const parsed = parseFloat(s);
|
2022-03-17 12:47:27 +01:00
|
|
|
const selfParsed = this.parseCustomLargeNumber(s);
|
|
|
|
// Check for one or more NaN values
|
2022-03-29 21:33:22 +02:00
|
|
|
if (isNaN(parsed) && numeralValue === null && isNaN(selfParsed)) {
|
|
|
|
// 3x NaN
|
2021-09-05 01:09:30 +02:00
|
|
|
return NaN;
|
2022-03-29 21:33:22 +02:00
|
|
|
} else if (isNaN(parsed) && isNaN(selfParsed)) {
|
|
|
|
// 2x NaN
|
2021-09-05 01:09:30 +02:00
|
|
|
return numeralValue;
|
2022-03-29 21:33:22 +02:00
|
|
|
} else if (numeralValue === null && isNaN(selfParsed)) {
|
|
|
|
// 2x NaN
|
2021-09-05 01:09:30 +02:00
|
|
|
return parsed;
|
2022-03-29 21:33:22 +02:00
|
|
|
} else if (isNaN(parsed) && numeralValue === null) {
|
|
|
|
// 2x NaN
|
2022-03-17 12:47:27 +01:00
|
|
|
return selfParsed;
|
2022-03-29 21:33:22 +02:00
|
|
|
} else if (isNaN(parsed)) {
|
|
|
|
// 1x NaN
|
2022-03-18 13:03:13 +01:00
|
|
|
return this.largestAbsoluteNumber(numeralValue, selfParsed);
|
2022-03-29 21:33:22 +02:00
|
|
|
} else if (numeralValue === null) {
|
|
|
|
// 1x NaN
|
2022-03-18 13:03:13 +01:00
|
|
|
return this.largestAbsoluteNumber(parsed, selfParsed);
|
2022-03-29 21:33:22 +02:00
|
|
|
} else if (isNaN(selfParsed)) {
|
|
|
|
// 1x NaN
|
2022-03-18 13:03:13 +01:00
|
|
|
return this.largestAbsoluteNumber(numeralValue, parsed);
|
2022-03-29 21:33:22 +02:00
|
|
|
} else {
|
|
|
|
// no NaN
|
2022-03-18 13:03:13 +01:00
|
|
|
return this.largestAbsoluteNumber(numeralValue, parsed, selfParsed);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
}
|
2018-09-12 17:53:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export const numeralWrapper = new NumeralFormatter();
|