Skip to content

Commit

Permalink
Merge branch 'release/v2.2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Ant1mas committed May 31, 2020
2 parents 1dee1e3 + 0621f1e commit 48ffaea
Show file tree
Hide file tree
Showing 11 changed files with 162 additions and 57 deletions.
33 changes: 25 additions & 8 deletions README-english.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,22 +159,23 @@ Currency of number.
| `'eur'` | Euro | 124 **евро** 42 **цента** |
| `'number'` | Number without currency | 124 **целых** 42 **сотых** |

<br/>
**Note**: For all common currencies except `number` set `fractionalPartMinLength: 2`. Also these currencies will be rounded to `2`.

- Own currency:

```js
{
currencyNameCases: ['рубль', 'рубля', 'рублей'], // Integer currency names
fractionalPartNameCases: ['копейка', 'копейки', 'копеек'], // Fractional number currency names
currencyNameCases: ['рубль', 'рубля', 'рублей'], // [1 рубль, 2-4 рубля, 5-9 рублей]
fractionalPartNameCases: ['копейка', 'копейки', 'копеек'],
currencyNounGender: {
integer: 0, // 0 => ('один', 'два'...)
fractionalPart: 1 // 1 => ('одна', 'две'...)
}
fractionalPartMinLength: 2
}
// or
{
currencyNameCases: ['сообщение', 'сообщения', 'сообщений'], // [1 сообщение, 2-4 сообщения, 5-9 сообщений]
currencyNameCases: ['сообщение', 'сообщения', 'сообщений'],
fractionalPartNameCases: ['', '', ''],
currencyNounGender: {
integer: 2, // 2 => ('одно', 'два'...)
Expand All @@ -185,6 +186,22 @@ Currency of number.

**Note**: If currency object will not be filled completely then missing data will be taken from default currency (`'rub'`).

#### Parameters of object `currency`

`currencyNameCases: (Array)`: Currency form name of integer part. 3 elements in array.

`fractionalPartNameCases: (Array)`: Currency form name of fractional part. 3 elements in array.

`currencyNounGender: (Object)`: Form of number: 0 - ("один"), 1 - ("одна"), 2 - ("одно").

- `integer` - For integer part.

- `fractionalPart` - For fractional part.

`fractionalPartMinLength: (number)`: Minimal length of fractional part. For example if set `3` then in fractional part mey be number `002`.

**Note**: In arrays `currencyNameCases` and `fractionalPartNameCases`: first element for digit 1 (1 `рубль`), second elemet for digits 2-4 (2 `рубля`), third element for digits 5-9 and 0 (5 `рублей`).

<br/>

```
Expand All @@ -203,25 +220,25 @@ Round number to specified precision.

- `-1` - Disable rounding.

**Note**: If option `currency` is a common currency (`rub` / `usd` / `eur`) then after rounding it will be rounded again to 2 digits. Also in this case the result always will have 2 digits in fractional part (for example "00", "05").
**Note**: If option `currency` is a common currency (`rub` / `usd` / `eur`) then after rounding it will be rounded again to 2 digits.

#### Example

```js
numberToWordsRu.convert('129.6789', {
currency: 'eur',
currency: 'rub',
roundNumber: 5,
});
// Сто двадцать девять рублей 68 копеек

numberToWordsRu.convert('129.6789', {
currency: 'eur',
currency: 'rub',
roundNumber: 1,
});
// Сто двадцать девять рублей 70 копеек

numberToWordsRu.convert('129.6789', {
currency: 'eur',
currency: 'rub',
roundNumber: 0,
});
// Сто тридцать рублей 00 копеек
Expand Down
37 changes: 27 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,22 +159,23 @@ currency: (string|Object)
| `'eur'` | Евро | 124 **евро** 42 **цента** |
| `'number'` | Число без реальной валюты | 124 **целых** 42 **сотых** |

<br/>
**Примечание**: Для всех стандартных валют, кроме `number` установлено `fractionalPartMinLength: 2`. Также эти валюты автоматически округляются до `2` знаков после запятой.

- Своя валюта:

```js
{
currencyNameCases: ['рубль', 'рубля', 'рублей'], // Падежи названия целой части числа
fractionalPartNameCases: ['копейка', 'копейки', 'копеек'], // Падежи названия дробной части числа
currencyNameCases: ['рубль', 'рубля', 'рублей'], // [1 рубль, 2-4 рубля, 5-9 рублей]
fractionalPartNameCases: ['копейка', 'копейки', 'копеек'],
currencyNounGender: {
integer: 0, // 0 => Мужской род ('один', 'два'...)
fractionalPart: 1 // 1 => Женский род ('одна', 'две'...)
}
},
fractionalPartMinLength: 2
}
// или
{
currencyNameCases: ['сообщение', 'сообщения', 'сообщений'], // [1 сообщение, 2-4 сообщения, 5-9 сообщений]
currencyNameCases: ['сообщение', 'сообщения', 'сообщений'],
fractionalPartNameCases: ['', '', ''],
currencyNounGender: {
integer: 2, // 2 => Средний род ('одно', 'два'...)
Expand All @@ -183,7 +184,23 @@ currency: (string|Object)
}
```

**Примечание**: Если объект валюты заполнить не полностью, то недостающие данные будут взяты из объекта валюты по умолчанию (`'rub'`).
**Примечание**: Если объект валюты заполнить не полностью, то недостающие параметры будут взяты из объекта валюты по умолчанию (`'rub'`).

#### Параметры объекта `currency`

`currencyNameCases: (Array)`: Формы названия валюты целой части числа. 3 элемента в массиве.

`fractionalPartNameCases: (Array)`: Формы названия валюты дробной части числа. 3 элемента в массиве.

`currencyNounGender: (Object)`: Род числа: 0 - мужской род (один), 1 - женский род (одна), 2 - средний род (одно).

- `integer` - Для целой части числа.

- `fractionalPart` - Для дробной части числа.

`fractionalPartMinLength: (number)`: Минимальное количество знаков, котрое может остаться в дробной части. Например, при значении `3` в дробной части возможно число `002`.

**Примечание**: В массивах `currencyNameCases` и `fractionalPartNameCases`: первый элемент для цифры 1 (1 `рубль`), второй элемент для цифр 2-4 (2 `рубля`), третий элемент для цифр 5-9 и 0 (5 `рублей`).

<br/>

Expand All @@ -203,25 +220,25 @@ roundNumber: (number)

- `-1` - Отключить округление.

**Примечание**: Если опция `currency` является стандартной валютой (`'rub'` / `'usd'` / `'eur'`), то даже после округления число будет еще раз округлено до 2 знаков после запятой. Также в этом случае у результата в дробной части всегда будет 2 знака (например "00", "05").
**Примечание**: Если опция `currency` является стандартной валютой (`'rub'` / `'usd'` / `'eur'`), то даже после округления число будет еще раз округлено до 2 знаков после запятой.

#### Пример

```js
numberToWordsRu.convert('129.6789', {
currency: 'eur',
currency: 'rub',
roundNumber: 5,
});
// Сто двадцать девять рублей 68 копеек

numberToWordsRu.convert('129.6789', {
currency: 'eur',
currency: 'rub',
roundNumber: 1,
});
// Сто двадцать девять рублей 70 копеек

numberToWordsRu.convert('129.6789', {
currency: 'eur',
currency: 'rub',
roundNumber: 0,
});
// Сто тридцать рублей 00 копеек
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "number-to-words-ru",
"version": "2.1.2",
"version": "2.2.0",
"description": "Convert a number to words on russian language.",
"license": "MIT",
"repository": "Ant1mas/number-to-words-ru",
Expand Down
25 changes: 8 additions & 17 deletions src/combineResultData.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import textValues from 'textValues';
import getOptions from 'getOptions';
import roundNumber from 'roundNumber';
import fractionalPartToMinLength from 'fractionalPartToMinLength';
import getCurrencyObject from 'getCurrencyObject';
import numberToScales from 'numberToScales';
import convertsEachScaleToWords from 'convertsEachScaleToWords';
Expand Down Expand Up @@ -30,28 +31,18 @@ const combineResultData = (numberArray, options) => {
convertedNumberArr[0] = '-';
}
}
// Если разделитель - не дробная черта
if (numberArray[2] !== '/') {
// Округлить число до заданной точности
modifiedNumberArray = roundNumber(numberArray, useOptions.roundNumber);
}
// Округлить число до заданной точности
modifiedNumberArray = roundNumber(numberArray, useOptions.roundNumber);
// Если указана валюта
if (
typeof useOptions.currency === 'string' &&
useOptions.currency !== 'number'
) {
// Если разделитель - не дробная черта
if (numberArray[2] !== '/') {
// Округлить число до 2 знаков после запятой
modifiedNumberArray = roundNumber(modifiedNumberArray, 2);
// Если в дробной части < 2 цифр
if (modifiedNumberArray[3].length < 2) {
// Заполнить нулями
modifiedNumberArray[3] = modifiedNumberArray[3] + '0'
.repeat(2 - modifiedNumberArray[3].length);
}
}
// Округлить число до 2 знаков после запятой
modifiedNumberArray = roundNumber(modifiedNumberArray, 2);
}
// Обеспечить минимальную длину дробной части числа
modifiedNumberArray = fractionalPartToMinLength(modifiedNumberArray, currencyObject);
// Если нужно отображать целую часть числа
if (useOptions.showNumberParts.integer === true) {
convertedNumberArr[1] = modifiedNumberArray[1];
Expand Down Expand Up @@ -105,7 +96,7 @@ const combineResultData = (numberArray, options) => {
).result;
}
} else {
// Если не нужно конвертировать в слова
// Если не нужно конвертировать число в слова
// Если валюта "number"
if (useOptions.currency === 'number') {
// Если в дробной части есть цифры
Expand Down
23 changes: 23 additions & 0 deletions src/fractionalPartToMinLength.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Сделать так, чтобы у дробной части числа
* минимальная длина соответствовала currencyObject.fractionalPartMinLength
* @param {Array} numberArray - Число в виде массива ['-', '150', '/', '25'].
* @param {Object} currencyObject - Объект с параметрами валюты.
* @return {Array} Обновленный массив числа.
*/
const fractionalPartToMinLength = (numberArray, currencyObject) => {
// Если разделитель - дробная черта
if (numberArray[2] === '/') {
return numberArray;
}
const updatedNumberArray = [...numberArray];
// Если в дробной части цифр меньше, чем fractionalPartMinLength
if (updatedNumberArray[3].length < currencyObject.fractionalPartMinLength) {
// Заполнить нулями
updatedNumberArray[3] = updatedNumberArray[3] + '0'
.repeat(currencyObject.fractionalPartMinLength - updatedNumberArray[3].length);
}
return updatedNumberArray;
};

export default fractionalPartToMinLength;
22 changes: 8 additions & 14 deletions src/getCurrencyObject.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import textValues from 'textValues';
import defaultOptions from 'defaultOptions';
import stringCurrencies from 'stringCurrencies';
import updateObjectDeep from 'updateObjectDeep';

/**
Expand All @@ -10,22 +9,17 @@ import updateObjectDeep from 'updateObjectDeep';
*/
const getCurrencyObject = (convertOptions) => {
let currencyObject;
// Если отображение без валюты
if (convertOptions.currency === 'number') {
currencyObject = {
currencyNameCases: ['целая', 'целых', 'целых'],
getFractionalPartNameCases: textValues.getFractionalUnits,
currencyNounGender: {
integer: 1,
fractionalPart: 1,
},
};
// Если валюта указана словами
} else if (typeof convertOptions.currency === 'string') {
if (typeof convertOptions.currency === 'string') {
// Если такая валюта есть в списке
if (textValues.currency[convertOptions.currency] !== undefined) {
// Получить данные найденной валюты
currencyObject = textValues.currency[convertOptions.currency];
// Если валюта указана как "number"
if (convertOptions.currency === 'number') {
// Добавить функцию для заполнения fractionalPartNameCases
currencyObject.getFractionalPartNameCases = textValues.getFractionalUnits;
}
} else {
throw new Error(
'Wrong currency name [' + convertOptions.currency + ']. '
Expand All @@ -35,13 +29,13 @@ const getCurrencyObject = (convertOptions) => {
// Если валюта описана объектом
} else if (typeof convertOptions.currency === 'object') {
// Объект валюты по умолчанию
const defaultCurrencyObject = stringCurrencies[defaultOptions['currency']];
const defaultCurrencyObject = textValues.currency[defaultOptions['currency']];
// Обновить объект валюты новым объектом валюты
const updatedCurrencyObject = updateObjectDeep(defaultCurrencyObject, convertOptions.currency);
// Если объект оформлен правильно
if (
typeof updatedCurrencyObject === 'object' &&
Object.keys(updatedCurrencyObject).length === 3 &&
Object.keys(updatedCurrencyObject).length === 4 &&
updatedCurrencyObject.currencyNameCases.length === 3 &&
updatedCurrencyObject.fractionalPartNameCases.length === 3 &&
typeof updatedCurrencyObject.currencyNounGender === 'object' &&
Expand Down
2 changes: 1 addition & 1 deletion src/methods/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import combineResultData from 'combineResultData';
*/
const convert = (number, options = {}) => {
// Обработать введенное число
const numberArray = splitNumberToArray(number);
const numberArray = splitNumberToArray(number, options);
// Собрать конечный словестный результат
const convertedNumberString = combineResultData(numberArray, options);
return convertedNumberString;
Expand Down
4 changes: 4 additions & 0 deletions src/roundNumber.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ const roundNumber = (numberArray, precision = 2) => {
if (precision < 0) {
return numberArray;
}
// Если разделитель - дробная черта то не округлять
if (numberArray[2] === '/') {
return numberArray;
}
// Если количество знаков после запятой <= precision, то не округлять
if (numberArray[3].length <= precision) {
return numberArray;
Expand Down
10 changes: 7 additions & 3 deletions src/splitNumberToArray.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/**
* Разделить число на части.
* @param {(number|string)} number - Число, которое нужно обработать.
* @param {Object} options - Параметры конвертирования.
* @return {Array} Обработанное число в виде ['-', '150', '/', '25'].
*/
const splitNumberToArray = (number) => {
const splitNumberToArray = (number, options) => {
// Максимальная длинна целой части числа
const maxIntegerPartLength = 306;
// Конвертировать в String
Expand Down Expand Up @@ -33,8 +34,11 @@ const splitNumberToArray = (number) => {
numberArray[3] = numberArray[3] === undefined ? '' : numberArray[3];
// Убрать лишние нули из целой части
numberArray[1] = numberArray[1].replace(/^0+/, '');
// Если разделитель не дробная черта
if (numberArray[2] !== '/') {
// Если разделитель не дробная черта и валюта не 'number'
if (
numberArray[2] !== '/'
&& options.currency !== 'number'
) {
// Убрать лишние нули из дробной части
numberArray[3] = numberArray[3]
.split('')
Expand Down
14 changes: 14 additions & 0 deletions src/stringCurrencies.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
const defaultParams = {
fractionalPartMinLength: 2,
};

const stringCurrencies = {
number: {
currencyNameCases: ['целая', 'целых', 'целых'],
currencyNounGender: {
integer: 1,
fractionalPart: 1,
},
},
rub: {
...defaultParams,
currencyNameCases: ['рубль', 'рубля', 'рублей'],
fractionalPartNameCases: ['копейка', 'копейки', 'копеек'],
currencyNounGender: {
Expand All @@ -8,6 +20,7 @@ const stringCurrencies = {
},
},
usd: {
...defaultParams,
currencyNameCases: ['доллар', 'доллара', 'долларов'],
fractionalPartNameCases: ['цент', 'цента', 'центов'],
currencyNounGender: {
Expand All @@ -16,6 +29,7 @@ const stringCurrencies = {
},
},
eur: {
...defaultParams,
currencyNameCases: ['евро', 'евро', 'евро'],
fractionalPartNameCases: ['цент', 'цента', 'центов'],
currencyNounGender: {
Expand Down
Loading

0 comments on commit 48ffaea

Please sign in to comment.