@vicimpa/rubles
Version:
Стоимость прописью
256 lines (244 loc) • 12.6 kB
JavaScript
const joinWord = (input, index = 0) => {
return input[0] + input[index + 1];
};
function counterWord(input, counter) {
const units = counter % 10;
if (counter > 10 && counter < 20)
return joinWord(input, 0);
if (units == 1)
return joinWord(input, 1);
if (units > 1 && units < 5)
return joinWord(input, 2);
return joinWord(input, 0);
}
const firstUpper = (input) => {
return input.slice(0, 1).toUpperCase() + input.slice(1).toLocaleLowerCase();
};
var currency = [
['рубл', 'ей', 'ь', 'я'],
['копе', 'ек', 'йка', 'йки']
];
const parseNumber = (input) => {
return input
.toString()
.replace(/[\s\t\_\-]+/g, '')
.split(/[\.\,]/);
};
const numberFormat = (input, sep = ' ', precision = 2, dot = '.') => {
let [base, dec = ''] = parseNumber(input);
const segments = [];
while (base.length) {
segments.unshift(base.slice(-3));
base = base.slice(0, -3);
}
return [segments.join(sep), dec.slice(0, precision)].filter(e => e).join(dot);
};
// Все варианты написания разрядов прописью скомпануем в один небольшой массив
var bigDischarges = [
["…n-лион", "ов", "", "а"], // используется для всех неизвестно больших разрядов
["тысяч", "", "а", "и"],
["миллион", "ов", "", "а"],
["миллиард", "ов", "", "а"],
["триллион", "ов", "", "а"],
["квадриллион", "ов", "", "а"],
["квинтиллион", "ов", "", "а"],
["секстиллион", "ов", "", "а"],
["септиллион", "ов", "", "а"],
["октиллион", "ов", "", "а"],
["нониллион", "ов", "", "а"],
["дециллион", "ов", "", "а"],
["ундециллион", "ов", "", "а"],
["додециллион", "ов", "", "а"],
["тредециллион", "ов", "", "а"],
["кваттуордециллион", "ов", "", "а"],
["квиндециллион", "ов", "", "а"],
["седециллион", "ов", "", "а"],
["септдециллион", "ов", "", "а"],
["октодециллион", "ов", "", "а"],
["новемдециллион", "ов", "", "а"],
["вигинтиллион", "ов", "", "а"],
["анвигинтиллион", "ов", "", "а"],
["дуовигинтиллион", "ов", "", "а"],
["тревигинтиллион", "ов", "", "а"],
["кватторвигинтиллион", "ов", "", "а"],
["квинвигинтиллион", "ов", "", "а"],
["сексвигинтиллион", "ов", "", "а"],
["септемвигинтиллион", "ов", "", "а"],
["октовигинтиллион", "ов", "", "а"],
["новемвигинтиллион", "ов", "", "а"],
["тригинтиллион", "ов", "", "а"],
["антригинтиллион", "ов", "", "а"],
["дуотригинтиллион", "ов", "", "а"],
["третригинтиллион", "ов", "", "а"], // 10 в 102
["кваттуортригинтиллион", "ов", "", "а"],
["квинтригинтиллион", "ов", "", "а"],
["секстригинтиллион", "ов", "", "а"],
["септентригинтиллион", "ов", "", "а"],
["октотригинтиллион", "ов", "", "а"],
["новемтригинтиллион", "ов", "", "а"],
["квадрагинтиллион", "ов", "", "а"], // 10 в 123
["унквадрагинтиллион", "ов", "", "а"],
["дуоквадрагинтиллион", "ов", "", "а"],
["треквадрагинтиллион", "ов", "", "а"],
["кваторквадрагинтиллион", "ов", "", "а"],
["квинквадрагинтиллион", "ов", "", "а"],
["сексквадрагинтиллион", "ов", "", "а"],
["септенквадрагинтиллион", "ов", "", "а"],
["октоквадрагинтиллион", "ов", "", "а"],
["новемквадрагинтиллион", "ов", "", "а"],
["квинквагинтиллион", "ов", "", "а"],
["унквинкагинтиллион", "ов", "", "а"],
["дуоквинкагинтиллион", "ов", "", "а"],
["треквинкагинтиллион", "ов", "", "а"],
["кваторквинкагинтиллион", "ов", "", "а"],
["квинквинкагинтиллион", "ов", "", "а"],
["сексквинкагинтиллион", "ов", "", "а"],
["септенквинкагинтиллион", "ов", "", "а"],
["октоквинкагинтиллион", "ов", "", "а"],
["новемквинкагинтиллион", "ов", "", "а"],
["сексагинтиллион", "ов", "", "а"],
["унсексагинтиллион", "ов", "", "а"],
["дуосексагинтиллион", "ов", "", "а"],
["тресексагинтиллион", "ов", "", "а"],
["кваторсексагинтиллион", "ов", "", "а"],
["квинсексагинтиллион", "ов", "", "а"],
["секссексагинтиллион", "ов", "", "а"],
["септенсексагинтиллион", "ов", "", "а"],
["октосексагинтиллион", "ов", "", "а"],
["новемсексагинтиллион", "ов", "", "а"],
["септагинтиллион", "ов", "", "а"],
["унсептагинтиллион", "ов", "", "а"],
["дуосептагинтиллион", "ов", "", "а"],
["тресептагинтиллион", "ов", "", "а"],
["кваторсептагинтиллион", "ов", "", "а"],
["квинсептагинтиллион", "ов", "", "а"],
["секссептагинтиллион", "ов", "", "а"],
["септенсептагинтиллион", "ов", "", "а"],
["октосептагинтиллион", "ов", "", "а"],
["новемсептагинтиллион", "ов", "", "а"],
["октогинтиллион", "ов", "", "а"],
["уноктогинтиллион", "ов", "", "а"],
["дуооктогинтиллион", "ов", "", "а"],
["треоктогинтиллион", "ов", "", "а"],
["кватороктогинтиллион", "ов", "", "а"],
["квиноктогинтиллион", "ов", "", "а"],
["сексоктогинтиллион", "ов", "", "а"],
["септоктогинтиллион", "ов", "", "а"],
["октооктогинтиллион", "ов", "", "а"],
["новемоктогинтиллион", "ов", "", "а"],
["нонагинтиллион", "ов", "", "а"],
["уннонагинтиллион", "ов", "", "а"],
["дуононагинтиллион", "ов", "", "а"],
["тренонагинтиллион", "ов", "", "а"],
["кваторнонагинтиллион", "ов", "", "а"],
["квиннонагинтиллион", "ов", "", "а"],
["секснонагинтиллион", "ов", "", "а"],
["септеннонагинтиллион", "ов", "", "а"],
["октононагинтиллион", "ов", "", "а"],
["новемнонагинтиллион", "ов", "", "а"],
["центиллион", "ов", "", "а"], // 10^303
["анцентиллион", "ов", "", "а"],
["дуоцентиллион", "ов", "", "а"], // 10^309
["трецентиллион", "ов", "", "а"],
["кватторцентиллион", "ов", "", "а"] // 10^315
// ["", "ов", "", "а"],
// ,[... список можно продолжить
];
// Все варианты написания разрядов прописью скомпануем в один небольшой массив
var smallDischarges = [
['ноль'],
['-', 'один', 'два', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять'],
['десять', 'одиннадцать', 'двенадцать', 'тринадцать', 'четырнадцать', 'пятнадцать', 'шестнадцать', 'семнадцать', 'восемнадцать', 'девятнадцать'],
['-', '-', 'двадцать', 'тридцать', 'сорок', 'пятьдесят', 'шестьдесят', 'семьдесят', 'восемьдесят', 'девяносто'],
['-', 'сто', 'двести', 'триста', 'четыреста', 'пятьсот', 'шестьсот', 'семьсот', 'восемьсот', 'девятьсот'],
['-', 'одна', 'две']
];
function numbersInWords(input, com = false, upper = false) {
const output = [];
let [num] = parseNumber(input);
let deep = 0;
if (!num || num === '0')
return upper ? firstUpper(smallDischarges[0][0]) : smallDischarges[0][0];
while (num.length) {
const row = [];
const current = +num.slice(-3);
num = num.slice(0, -3);
const hundreds = current / 100 | 0;
const dozens = current / 10 % 10 | 0;
const units = current % 10;
if (current) {
row.push(smallDischarges[4][hundreds]);
if (dozens === 1) {
row.push(smallDischarges[2][units]);
}
else {
row.push(smallDischarges[3][dozens]);
if (deep === 1 || deep == 0 && com) {
row.push(smallDischarges[5][units] ?? smallDischarges[1][units]);
}
else {
row.push(smallDischarges[1][units]);
}
}
if (deep) {
row.push(counterWord(bigDischarges[deep] ?? bigDischarges[0], current));
}
}
const rowString = row.filter(e => e && e != '-').join(' ');
if (rowString)
output.unshift(rowString);
deep++;
}
return upper ? firstUpper(output.join(' ')) : output.join(' ');
}
const formatRegExp = /\$([a-z]+)/gi;
function format(input, format = '$summString $summCurrency $pennyString $pennyCurrency') {
let [base = '0', dop = '00'] = parseNumber(input);
dop = dop.slice(0, 2);
dop = ('00' + dop).slice(-2);
return format.replace(formatRegExp, (find, arg) => {
switch (arg) {
case 'input': return numberFormat(input, undefined, 2);
case 'summ': return numberFormat(input, undefined, 0);
case 'summString': return numbersInWords(input);
case 'summCurrency': return counterWord(currency[0], +base.slice(-2));
case 'SummString': return firstUpper(numbersInWords(input));
case 'SummCurrency': return firstUpper(counterWord(currency[0], +base.slice(-2)));
case 'penny': return dop;
case 'pennyString': return numbersInWords(+dop, true);
case 'pennyCurrency': return counterWord(currency[1], +dop);
case 'PennyString': return firstUpper(numbersInWords(+dop, true));
case 'PennyCurrency': return firstUpper(counterWord(currency[1], +dop));
default: return find;
}
});
}
const testFunction = async (func, tests, showTest = true) => {
{
const runs = await Promise.all(tests.map(async ([args, result], i) => {
const output = await Promise.resolve()
.then(() => JSON.stringify(func(...args)))
.catch((e) => `${e}`);
return [
result !== undefined && showTest ? (output === JSON.stringify(result) ? 'Passed' : 'Fail') : '',
`${func.name}(${args.map(e => JSON.stringify(e)).join(', ')})`,
`// ${output}`
];
}));
const maxs = [0, 0, 0].map((max, i) => {
for (const r of runs) {
if (r[i].length > max)
max = r[i].length;
}
return max;
});
console.log('=> Run test', func.name + '()');
console.log(runs.map((run, i) => {
return `${(run.map((row, i) => {
return row + (' '.repeat(maxs[i] - row.length));
}).filter(e => e).join('\t'))}`;
}).join('\n'));
}
console.log(' ');
};
export { counterWord, firstUpper, format, joinWord, numberFormat, numbersInWords, parseNumber, testFunction };