@opengis/fastify-table
Version:
core-plugins
362 lines (342 loc) • 11.4 kB
JavaScript
/* eslint-disable prefer-destructuring */
function saveEval(jsCode, context = {}) {
// TODO eval
const addcontext = Object.keys(context).map((key) => `let ${key}=context["${key}"];`).join('');
// eslint-disable-next-line no-eval
return eval(addcontext + jsCode);
}
const mapNumbers = {
ua: {
0: [2, 1, 'нуль'],
1: [0, 2, 'одна', 'один'],
2: [1, 2, 'дві', 'два', 'дві'],
3: [1, 1, 'три'],
4: [1, 1, 'чотири'],
5: [2, 1, "п'ять"],
6: [2, 1, 'шість'],
7: [2, 1, 'сім'],
8: [2, 1, 'вісім'],
9: [2, 1, "дев'ять"],
10: [2, 1, 'десять'],
11: [2, 1, 'одинадцять'],
12: [2, 1, 'дванадцять'],
13: [2, 1, 'тринадцять'],
14: [2, 1, 'чотирнадцять'],
15: [2, 1, "п'ятнадцять"],
16: [2, 1, 'шістнадцять'],
17: [2, 1, 'сімнадцять'],
18: [2, 1, 'вісімнадцять'],
19: [2, 1, "дев'ятнадцять"],
20: [2, 1, 'двадцять'],
30: [2, 1, 'тридцять'],
40: [2, 1, 'сорок'],
50: [2, 1, "п'ятдесят"],
60: [2, 1, 'шістдесят'],
70: [2, 1, 'сімдесят'],
80: [2, 1, 'вісімдесят'],
90: [2, 1, "дев'яносто"],
100: [2, 1, 'сто'],
200: [2, 1, 'двісті'],
300: [2, 1, 'триста'],
400: [2, 1, 'чотириста'],
500: [2, 1, "п'ятсот"],
600: [2, 1, 'шістсот'],
700: [2, 1, 'сімсот'],
800: [2, 1, 'вісімсот'],
900: [2, 1, "дев'ятсот"],
},
ru: {
0: [2, 1, 'ноль'],
1: [0, 2, 'одна', 'один'],
2: [1, 2, 'две', 'два', 'две'],
3: [1, 1, 'три'],
4: [1, 1, 'четыре'],
5: [2, 1, 'пять'],
6: [2, 1, 'шесть'],
7: [2, 1, 'семь'],
8: [2, 1, 'восемь'],
9: [2, 1, 'девять'],
10: [2, 1, 'десять'],
11: [2, 1, 'одинадцать'],
12: [2, 1, 'двенадцать'],
13: [2, 1, 'тринадцать'],
14: [2, 1, 'четырнадцать'],
15: [2, 1, 'пятнадцать'],
16: [2, 1, 'шестнадцать'],
17: [2, 1, 'семнадцать'],
18: [2, 1, 'восемнадцать'],
19: [2, 1, 'девятнадцать'],
20: [2, 1, 'двадцать'],
30: [2, 1, 'тридцать'],
40: [2, 1, 'сорок'],
50: [2, 1, 'пятьдесят'],
60: [2, 1, 'шестьдесят'],
70: [2, 1, 'семьдесят'],
80: [2, 1, 'восемьдесят'],
90: [2, 1, 'девяносто'],
100: [2, 1, 'сто'],
200: [2, 1, 'двести'],
300: [2, 1, 'триста'],
400: [2, 1, 'четыреста'],
500: [2, 1, 'пятьсот'],
600: [2, 1, 'шестьсот'],
700: [2, 1, 'семьсот'],
800: [2, 1, 'восемьсот'],
900: [2, 1, 'девятьсот'],
},
};
const mapOrders = {
ua: [
{ _Gender: true, _arrStates: ['', '', ''] },
{ _Gender: true, _arrStates: ['тисяча', 'тисячі', 'тисяч'] },
{ _Gender: false, _arrStates: ['мільйон', 'мільйона', 'мільйонів'] },
{ _Gender: false, _arrStates: ['мільярд', 'мільярда', 'мільярдів'] },
{ _Gender: false, _arrStates: ['триліон', 'триліона', 'триліонів'] },
{
_Gender: true,
_arrStates: {
uah: ['грн.', 'грн.', 'грн.'],
rur: ['руб.', 'руб.', 'руб.'],
},
_bAddZeroWord: true,
},
{
_Gender: true,
_arrStates: ['ціла', 'цілих', 'цілих'],
_bAddZeroWord: true,
},
{ _Gender: true, _arrStates: ['', '', ''], _bAddZeroWord: true },
{
_Gender: true,
_arrStates: ['дол.', 'дол.', 'дол.'],
_bAddZeroWord: true,
},
{
_Gender: true,
_arrStates: ['грн.', 'грн.', 'грн.'],
_bAddZeroWord: true,
},
],
ru: [
{ _Gender: true, _arrStates: ['', '', ''] },
{ _Gender: true, _arrStates: ['тысяча', 'тысячи', 'тысяч'] },
{ _Gender: false, _arrStates: ['миллион', 'миллиона', 'миллионов'] },
{ _Gender: false, _arrStates: ['миллиард', 'миллиарда', 'миллиардов'] },
{ _Gender: false, _arrStates: ['триллион', 'триллиона', 'триллионов'] },
{
_Gender: true,
_arrStates: {
uah: ['грн.', 'грн.', 'грн.'],
rur: ['руб.', 'руб.', 'руб.'],
usd: ['дол.', 'дол.', 'дол.'],
},
_bAddZeroWord: true,
},
{
_Gender: true,
_arrStates: ['целых', 'целых', 'целых'],
_bAddZeroWord: true,
},
{ _Gender: true, _arrStates: ['', '', ''], _bAddZeroWord: true },
{
_Gender: true,
_arrStates: ['дол.', 'дол.', 'дол.'],
_bAddZeroWord: true,
},
],
};
const objCur = {
_Gender: false,
_arrStates: {
uah: ['грн.', 'грн.', 'грн.'],
rur: ['руб.', 'руб.', 'руб.'],
usd: ['дол.', 'дол.', 'дол.'],
num: { ru: 'цел.', ua: 'ціл.', en: 'int.' },
},
};
const objCoin = {
_Gender: false,
_arrStates: {
uah: 'коп.',
rur: 'коп.',
usd: 'цен.',
num: { ru: 'сот.', ua: 'сот.', en: 'hund.' },
},
};
// функции которые отвечают за форматирование
/**
* Formatting from number to string
*
* @example
* // returns 'дві'
* value(2, true, 'ua');
* @example
* // returns 'два'
* value(2, false, 'ua');
* @param {Number} dVal
* @param {Any} bGender
* @param {String} lang
* @returns {String} Returns a formatted string
*/
function value(dVal, bGender, lang) {
const dValNew = dVal || 0;
const xVal = mapNumbers[lang][dValNew];
if (xVal[1] === 1) {
return xVal[2];
}
return xVal[2 + (bGender ? 0 : 1)];
}
/**
* Add a number to array(arrRet) in capital form
*
* @example
* // returns null
* from0To999(arrRet, 404,
* oObjDesc:
* {
* _Gender: true,
* _bAddZeroWord: undefined,
* _arrStates: ['','',''],
* },
* lang: 'ru'
* })
* @param {Array} arrRet
* @param {Number} fValue
* @param {Object} [oObjDesc._Gender]
* @param {Object} [oObjDesc._bAddZeroWord]
* @param {Object} [oObjDesc._arrStates]
* @param oObjDesc
* @param {String} lang
*/
function from0To999(arrRet, fValue, oObjDesc, lang) {
let fValueNew = fValue || 0;
let nCurrState = 2;
if (Math.floor(fValueNew / 100) > 0) {
const fCurr = Math.floor(fValueNew / 100) * 100;
arrRet.push(value(fCurr, oObjDesc._Gender, lang));
nCurrState = mapNumbers[lang][fCurr][0];
fValueNew -= fCurr;
}
if (fValueNew === 0) {
arrRet.push(value(fValueNew, oObjDesc._Gender, lang));
nCurrState = mapNumbers[lang][fValueNew][0];
} else if (fValueNew < 20) {
if (Math.floor(fValueNew) > 0 || oObjDesc._bAddZeroWord) {
arrRet.push(value(fValueNew, oObjDesc._Gender, lang));
nCurrState = mapNumbers[lang][fValueNew][0];
}
} else {
const fCurr = Math.floor(fValueNew / 10) * 10;
arrRet.push(value(fCurr, oObjDesc._Gender, lang));
nCurrState = mapNumbers[lang][fCurr][0];
fValueNew -= fCurr;
if (Math.floor(fValueNew) > 0) {
arrRet.push(value(fValueNew, oObjDesc._Gender, lang));
nCurrState = mapNumbers[lang][fValueNew][0];
}
}
arrRet.push(oObjDesc._arrStates[nCurrState]);
}
/**
* Formatting from number to string
*
* @example
* // returns '404 (четыреста четыре) руб. 101 (сто одна) коп.'
* floatToSamplesInWordsUkr(404.1011001001, '%d (%dt) %curr %f (%ft) %coin', 3, 'ru', 'rur');
* @returns {String|Number} fAmount
* @param {String} resultStr
* @param {Number} exp
* @param {String} lang
* @param {String} currency
* @returns {String} Returns a formatted string
*/
function floatToSamplesInWordsUkr(fAmount, resultStr, exp, lang, currency) {
let resultStrNew = resultStr;
let fInt = Math.floor(parseInt(fAmount, 10) + 0.005); // ціла частина
const fDec = Math.floor((fAmount - fInt) * exp + 0.5); // дробова частина
let arrRet = [];
const arrSouthands = [];
for (; fInt > 0.9999; fInt /= 1000) {
arrSouthands.push(Math.floor(fInt % 1000));
}
if (arrSouthands.length === 0) {
arrSouthands.push(0);
}
for (let iSouth = arrSouthands.length - 1; iSouth >= 0; iSouth -= 1) {
from0To999(
arrRet,
arrSouthands[iSouth],
mapOrders[lang][iSouth],
lang,
);
}
// опрацювуЇмо формат
resultStrNew = resultStrNew.replace(
/%dt/,
arrRet.join(' ').replace(' )', ')').trim(),
);
resultStrNew = resultStrNew.replace(
/%d/,
Math.floor(parseInt(fAmount, 10) + 0.005),
);
if (currency !== 'num' && objCur._arrStates[currency]) { resultStrNew = resultStrNew.replace(/%curr/, objCur._arrStates[currency][0]); } else {
resultStrNew = resultStrNew.replace(
/%curr/,
objCur._arrStates[lang === 'ru' ? 'rur' : lang][0],
);
}
// опрацьовуЇмо дробову частину
arrRet = []; // опустошуЇмо масив для запису в нього тільки дробовоњ частини
from0To999(arrRet, fDec, mapOrders[lang][0], lang);
// опрацювуЇмо формат
resultStrNew = resultStrNew.replace(
/%ft/,
arrRet.join(' ').replace(' )', ')').trim(),
);
resultStrNew = resultStrNew.replace(/%f/, fDec);
if (currency !== 'num' && objCur._arrStates[currency]) { resultStrNew = resultStrNew.replace(/%coin/, objCoin._arrStates[currency]); } else {
resultStrNew = resultStrNew.replace(
/%coin/,
objCoin._arrStates[lang === 'ru' ? 'rur' : lang],
);
}
return resultStrNew;
}
/**
* Formatting from number to string
*
* @summary Formatting from number to string
* @priority 0
* @deprecated true
* @type helper
* @alias formatNum
* @param {Number} round Округлення
* @param {String} currency Валюта
* @param {String} lang Мова на якій видати інформацію
* @param {String} format Шаблон вигляду результату
* @param {String|Number} data Число для форматування
* @returns {String} Returns HTML
*/
export default function formatNum(data, options = {}) {
let name = data;
if (!name) { name = 0; } // в случае значения NULL
if (typeof name === 'string' && !name.match(/^[a-zA-Z0-9.]+$/g)) {
let exec = name;
exec = exec.replace(
/([a-zA-Z_.]{3,100}[0-9]*)/g,
'options.data.root.$1',
);
name = saveEval(exec);
name = name ? parseFloat(name) : 0;
if (options.hash.round) name = name.toFixed(options.hash.round);
}
const opt = options.hash; // додатков≥ опц≥њ
const currency = opt.currency || 'uah';
const lang = opt.lang || 'ua';
// if(['ru','ua'].indexOf(lang)==-1)
// lang=(['ru','ua'].indexOf(window.lang)>-1?window.lang:'ua');
const round = opt.round || 2;
const exp = 10 ** round; // к≥льк≥сть знак≥в псл¤ коми
const resultStr = opt.format || '%d (%dt) %curr %f (%ft) %coin';
return floatToSamplesInWordsUkr(name, resultStr, exp, lang, currency);
};