UNPKG

@vicimpa/rubles

Version:
256 lines (244 loc) 12.6 kB
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 };