Skip to content

Commit

Permalink
fix(wordsToNumber): make it functional
Browse files Browse the repository at this point in the history
  • Loading branch information
moh3n9595 committed Apr 23, 2021
1 parent 1b209af commit 82b1b03
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 102 deletions.
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,31 +103,31 @@ Let's take a look at what an example test case would look like using Persian-too
| `addCommas` | Commas will be added to the Result | `false`
- Convert with no option
```javascript
import { WordsToNumber } from "@persian-tools/persian-tools";
import { wordsToNumber } from "@persian-tools/persian-tools";

WordsToNumber.convert("منفی سه هزارمین") // -3000
WordsToNumber.convert("منفی سه هزارم") // -3000
WordsToNumber.convert("منفی سه هزار") // -3000
WordsToNumber.convert("سه هزار دویست و دوازده") // 3212
WordsToNumber.convert("دوازده هزار بیست دو") // 12022
wordsToNumber("منفی سه هزارمین") // -3000
wordsToNumber("منفی سه هزارم") // -3000
wordsToNumber("منفی سه هزار") // -3000
wordsToNumber("سه هزار دویست و دوازده") // 3212
wordsToNumber("دوازده هزار بیست دو") // 12022
```
- Digits converter
```js
WordsToNumber.convert("منفی سه هزارمین", { digits: "fa" }) // "-۳۰۰۰"
WordsToNumber.convert("دوازده هزار بیست دو", { digits: "fa" }) // ۱۲۰۲۲
wordsToNumber("منفی سه هزارمین", { digits: "fa" }) // "-۳۰۰۰"
wordsToNumber("دوازده هزار بیست دو", { digits: "fa" }) // ۱۲۰۲۲
```
- Add commas
```js
WordsToNumber.convert("منفی سه هزارمین", { addCommas: true }) // "-3,000"
WordsToNumber.convert("دوازده هزار بیست دو", { addCommas: true }) // "12,022"
wordsToNumber("منفی سه هزارمین", { addCommas: true }) // "-3,000"
wordsToNumber("دوازده هزار بیست دو", { addCommas: true }) // "12,022"
```
- Fuzzy typo fixer(`v1.5.0`):
```javascript
import { WordsToNumber } from "@persian-tools/persian-tools";

WordsToNumber.convert("یگصد و بنجاه هزار", { fuzzy: true }) // "150000"
WordsToNumber.convert("دویشت ر بیشت هزار", { fuzzy: true }) // "220000"
WordsToNumber.convert("منقی ضد", { fuzzy: true }) // "-100"
wordsToNumber("یگصد و بنجاه هزار", { fuzzy: true }) // "150000"
wordsToNumber("دویشت ر بیشت هزار", { fuzzy: true }) // "220000"
wordsToNumber("منقی ضد", { fuzzy: true }) // "-100"
```

### Convert Numbers to Persian words
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export { isPersian, hasPersian } from "./modules/isPersian";
export { default as toPersianChars } from "./modules/toPersianChars";
// String and Number Converter and their utilities
export { default as NumberToWords, NumberToWordsOptions } from "./modules/numberToWords";
export { default as WordsToNumber, WordsToNumberOptions } from "./modules/wordsToNumber";
export { default as wordsToNumber, WordsToNumberOptions } from "./modules/wordsToNumber";
export { default as removeOrdinalSuffix } from "./modules/removeOrdinalSuffix";
export { default as addOrdinalSuffix } from "./modules/addOrdinalSuffix/addOrdinalSuffix";
// Add and Remove Commas
Expand Down
112 changes: 51 additions & 61 deletions src/modules/wordsToNumber/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,76 +23,66 @@ export interface WordsToNumberOptions {
fuzzy?: boolean;
}

class WordsToNumber {
/**
* Convert to numbers
*
* @method WordsToNumber
* @param {string} words
* @param {WordsToNumberOptions} options
* @return Converted words to number. e.g: 350000
*/
convert<TResult extends string | number>(
words: string,
{ digits = "en", addCommas: shouldAddCommas = false, fuzzy: isEnabledFuzzy = false }: WordsToNumberOptions = {},
): TResult {
if (!words) return "" as TResult;
function compute(tokens: string[]): number {
let sum = 0;
let isNegative = false;

// Remove ordinal suffixes
words = words.replace(new RegExp("مین$", "ig"), "");
words = removeOrdinalSuffix(words)!;
// Fix Persian typo's if enabled if this option is enabled
const classified = isEnabledFuzzy ? fuzzy(words) : words;
const computeNumbers = this.compute(this.tokenize(classified!));
const addCommasIfNeeded: string | number = shouldAddCommas
? addCommas(computeNumbers)
: (computeNumbers as number);
tokens.forEach((token) => {
token = digitsFaToEn(token)!;

if (digits === "fa") {
return digitsEnToFa(addCommasIfNeeded) as TResult;
} else if (digits === "ar") {
return digitsEnToAr(addCommasIfNeeded) as TResult;
if (token === PREFIXES[0]) {
isNegative = true;
} else if (UNITS[token] != null) {
sum += UNITS[token];
} else if (TEN[token] != null) {
sum += TEN[token];
} else if (!isNaN(Number(token))) {
sum += parseInt(token, 10);
} else {
return addCommasIfNeeded as TResult;
sum *= MAGNITUDE[token];
}
});
return isNegative ? sum * -1 : sum;
}

return (digits === "fa" ? digitsEnToFa(addCommasIfNeeded) : addCommasIfNeeded) as TResult;
}
private tokenize(words: string): string[] {
words = replaceArray(words, TYPO_LIST);
function tokenize(words: string): string[] {
words = replaceArray(words, TYPO_LIST);

const result: string[] = [];
const slittedWords: string[] = words.split(" ");
slittedWords.forEach((word) => {
return word === JOINERS[0] ? "" : result.push(word);
});
const result: string[] = [];
const slittedWords: string[] = words.split(" ");
slittedWords.forEach((word) => {
return word === JOINERS[0] ? "" : result.push(word);
});

return result;
}
return result;
}

private compute(tokens: string[]): number {
let sum = 0;
let isNegative = false;
/**
*
* Convert to numbers
*
* @category Number conversion
* @return Converted words to number. e.g: 350000
*/
export default function wordsToNumber<TResult extends string | number>(
words: string,
{ digits = "en", addCommas: shouldAddCommas = false, fuzzy: isEnabledFuzzy = false }: WordsToNumberOptions = {},
): TResult {
if (!words) return "" as TResult;

tokens.forEach((token) => {
token = digitsFaToEn(token)!;
// Remove ordinal suffixes
words = words.replace(new RegExp("مین$", "ig"), "");
words = removeOrdinalSuffix(words)!;
// Fix Persian typo's if enabled if this option is enabled
const classified = isEnabledFuzzy ? fuzzy(words) : words;
const computeNumbers = compute(tokenize(classified!));
const addCommasIfNeeded: string | number = shouldAddCommas ? addCommas(computeNumbers) : (computeNumbers as number);

if (token === PREFIXES[0]) {
isNegative = true;
} else if (UNITS[token] != null) {
sum += UNITS[token];
} else if (TEN[token] != null) {
sum += TEN[token];
} else if (!isNaN(Number(token))) {
sum += parseInt(token, 10);
} else {
sum *= MAGNITUDE[token];
}
});
return isNegative ? sum * -1 : sum;
if (digits === "fa") {
return digitsEnToFa(addCommasIfNeeded) as TResult;
} else if (digits === "ar") {
return digitsEnToAr(addCommasIfNeeded) as TResult;
} else {
return addCommasIfNeeded as TResult;
}
}

const WordsToNumberInstance = new WordsToNumber();

export default WordsToNumberInstance;
54 changes: 27 additions & 27 deletions test/wordsToNumber.spec.ts
Original file line number Diff line number Diff line change
@@ -1,76 +1,76 @@
import { WordsToNumber } from "../src";
import { wordsToNumber } from "../src";

describe("WordsToNumber", () => {
describe("wordsToNumber", () => {
it("Should convert truly", () => {
expect(WordsToNumber.convert<number>("منفی سه هزار")).toEqual(-3000);
expect(WordsToNumber.convert<number>("سه هزار دویست و دوازده")).toEqual(3212);
expect(WordsToNumber.convert<number>("دوازده هزار بیست دو")).toEqual(12022);
expect(wordsToNumber<number>("منفی سه هزار")).toEqual(-3000);
expect(wordsToNumber<number>("سه هزار دویست و دوازده")).toEqual(3212);
expect(wordsToNumber<number>("دوازده هزار بیست دو")).toEqual(12022);
expect(
WordsToNumber.convert<string>("دوازده هزار بیست دو", { addCommas: true }),
wordsToNumber<string>("دوازده هزار بیست دو", { addCommas: true }),
).toEqual("12,022");
expect(
WordsToNumber.convert<string>("دوازده هزار و بیست و دو", { addCommas: true }),
wordsToNumber<string>("دوازده هزار و بیست و دو", { addCommas: true }),
).toEqual("12,022");
});

it("Should convert truly and convert to Arabic digits", () => {
expect(
WordsToNumber.convert<string>("منفی سه هزار", { digits: "ar" }),
wordsToNumber<string>("منفی سه هزار", { digits: "ar" }),
).toEqual("-۳۰۰۰");
expect(
WordsToNumber.convert<string>("سه هزار دویست و دوازده", { digits: "ar" }),
wordsToNumber<string>("سه هزار دویست و دوازده", { digits: "ar" }),
).toEqual("۳۲۱۲");
expect(
WordsToNumber.convert<string>("دوازده هزار بیست دو", { digits: "ar" }),
wordsToNumber<string>("دوازده هزار بیست دو", { digits: "ar" }),
).toEqual("۱۲۰۲۲");
expect(
WordsToNumber.convert<string>("دوازده هزار بیست دو", { digits: "ar", addCommas: true }),
wordsToNumber<string>("دوازده هزار بیست دو", { digits: "ar", addCommas: true }),
).toEqual("۱۲,۰۲۲");
expect(
WordsToNumber.convert<string>("دوازده هزار و بیست و دو", { digits: "ar", addCommas: true }),
wordsToNumber<string>("دوازده هزار و بیست و دو", { digits: "ar", addCommas: true }),
).toEqual("۱۲,۰۲۲");
expect(
WordsToNumber.convert<string>("چهارصد پنجاه هزار", { digits: "ar", addCommas: true }),
wordsToNumber<string>("چهارصد پنجاه هزار", { digits: "ar", addCommas: true }),
).toEqual("٤٥۰,۰۰۰");
expect(
WordsToNumber.convert<string>("چهارصد پنجاه هزار", { digits: "ar" }),
wordsToNumber<string>("چهارصد پنجاه هزار", { digits: "ar" }),
).toEqual("٤٥۰۰۰۰");
});

it("Should convert with ordinal words", () => {
expect(
WordsToNumber.convert<string>("منفی ۳ هزار", { digits: "fa", addCommas: true }),
wordsToNumber<string>("منفی ۳ هزار", { digits: "fa", addCommas: true }),
).toEqual("-۳,۰۰۰");
expect(
WordsToNumber.convert<string>("منفی 3 هزار و 200", { digits: "fa", addCommas: true }),
wordsToNumber<string>("منفی 3 هزار و 200", { digits: "fa", addCommas: true }),
).toEqual("-۳,۲۰۰");
expect(
WordsToNumber.convert<string>("منفی سه هزارمین", { digits: "fa", addCommas: true }),
wordsToNumber<string>("منفی سه هزارمین", { digits: "fa", addCommas: true }),
).toEqual("-۳,۰۰۰");
expect(
WordsToNumber.convert<string>("منفی سه هزارمین", { digits: "fa" }),
wordsToNumber<string>("منفی سه هزارمین", { digits: "fa" }),
).toEqual("-۳۰۰۰");
expect(WordsToNumber.convert<number>("منفی سه هزارمین")).toEqual(-3000);
expect(WordsToNumber.convert<number>("منفی سه هزارم")).toEqual(-3000);
expect(WordsToNumber.convert<string>("منفی سه هزارمین")).not.toEqual("-3000");
expect(String(WordsToNumber.convert<number>("منفی سه هزارمین"))).toHaveLength(5);
expect(WordsToNumber.convert<number>("منفی سی اُم")).toEqual(-30);
expect(wordsToNumber<number>("منفی سه هزارمین")).toEqual(-3000);
expect(wordsToNumber<number>("منفی سه هزارم")).toEqual(-3000);
expect(wordsToNumber<string>("منفی سه هزارمین")).not.toEqual("-3000");
expect(String(wordsToNumber<number>("منفی سه هزارمین"))).toHaveLength(5);
expect(wordsToNumber<number>("منفی سی اُم")).toEqual(-30);
expect(
WordsToNumber.convert<number>("سی و سوم", { fuzzy: true }),
wordsToNumber<number>("سی و سوم", { fuzzy: true }),
).toEqual(33);
});

it("Should return undefined", () => {
expect(
WordsToNumber.convert<string>("", { digits: "fa", addCommas: true }),
wordsToNumber<string>("", { digits: "fa", addCommas: true }),
).toEqual("");
// @ts-ignore
expect(WordsToNumber.convert()).toEqual("");
expect(wordsToNumber()).toEqual("");
});

it("Should works with fuzzy model", () => {
expect(
WordsToNumber.convert<number>("ضد و بنچاه و دو", { fuzzy: true }),
wordsToNumber<number>("ضد و بنچاه و دو", { fuzzy: true }),
).toEqual(152);
});
});

0 comments on commit 82b1b03

Please sign in to comment.