Add basic parsing for streams and values.master
@@ -90,3 +90,4 @@ dist | |||
.yarn/unplugged | |||
.yarn/build-state.yml | |||
.pnp.* | |||
tests/output |
@@ -27,6 +27,7 @@ | |||
"author": "TheoryOfNekomata <allan.crisostomo@outlook.com> (https://modal.sh)", | |||
"module": "dist/number-name.esm.js", | |||
"devDependencies": { | |||
"@types/node": "^14.6.0", | |||
"fast-check": "^2.1.0", | |||
"husky": "^4.2.5", | |||
"tsdx": "^0.13.2", | |||
@@ -0,0 +1,43 @@ | |||
import NumberSystem from './NumberSystem' | |||
import ConverterStream from './ConverterStream' | |||
import { ReadStreamOptions, ConvertOptions } from './common' | |||
export default class Converter { | |||
constructor(private readonly system: NumberSystem) {} | |||
convert(value: string | number | bigint, options: ConvertOptions) { | |||
let converted: string[] = [] | |||
switch (typeof value!) { | |||
case 'string': | |||
return '' | |||
case 'bigint': | |||
case 'number': | |||
let current = value as number | |||
let thousandPower = 0 | |||
while (current > 0) { | |||
const hundreds = Math.floor((current % 1000) / 100) | |||
const tens = Math.floor((current % 100) / 10) | |||
const ones = Math.floor(current % 10) | |||
if (!(ones === 0 && tens === 0 && hundreds === 0)) { | |||
if (thousandPower > 0) { | |||
const { scale = 'short' } = options | |||
converted.unshift(this.system.getKiloName[scale!]!(thousandPower)) | |||
} | |||
converted.unshift(this.system.getKiloCount(hundreds, tens, ones)) | |||
} | |||
thousandPower = thousandPower + 1 | |||
current = Math.floor(current / 1000) | |||
} | |||
return converted.join(' ') | |||
default: | |||
break | |||
} | |||
throw TypeError('Invalid argument passed to value.') | |||
} | |||
readStream(options: ReadStreamOptions): ConverterStream { | |||
const { scale = 'short', encoding = 'utf-8' } = options | |||
return new ConverterStream(this.system, { scale, encoding }) | |||
} | |||
} |
@@ -0,0 +1,45 @@ | |||
import { Transform } from 'stream' | |||
import NumberSystem from './NumberSystem' | |||
import { ReadStreamOptions } from './common' | |||
export default class ConverterStream extends Transform { | |||
private thousandPower: number = 0 | |||
constructor(private readonly system: NumberSystem, private readonly options: ReadStreamOptions) { | |||
super() | |||
this.thousandPower = 0 | |||
} | |||
_transform(chunk: any, _encoding: BufferEncoding, callback: Function) { | |||
const { scale, encoding } = this.options | |||
const [ones = 0, tens = 0, hundreds = 0] = chunk | |||
.toString(encoding!) | |||
.split('') | |||
.filter((s: string) => /[0-9]/.test(s)) | |||
.map((d: string) => Number(d)) // todo use encoding | |||
if (!(ones === 0 && tens === 0 && hundreds === 0)) { | |||
if (this.thousandPower > 0) { | |||
this.push( | |||
this.system.getKiloName[scale!]!(this.thousandPower) | |||
.split('') | |||
.reverse() | |||
.join(''), | |||
) | |||
this.push(' ') | |||
} | |||
this.push( | |||
this.system | |||
.getKiloCount(hundreds, tens, ones) | |||
.split('') | |||
.reverse() | |||
.join(''), | |||
) | |||
this.push(' ') | |||
} | |||
this.thousandPower = this.thousandPower + 1 | |||
callback() | |||
} | |||
} |
@@ -2,9 +2,9 @@ export type GetKiloCount = (hundreds: number, tens: number, ones: number) => str | |||
export type GetKiloName = (thousandPower: number) => string | |||
export default interface NumberSystem { | |||
getKiloCount: GetKiloCount, | |||
getKiloCount: GetKiloCount | |||
getKiloName: { | |||
short?: GetKiloName, | |||
long?: GetKiloName, | |||
short?: GetKiloName | |||
long?: GetKiloName | |||
} | |||
} |
@@ -0,0 +1,14 @@ | |||
export default interface NumberSystemNameTable { | |||
units: string[10] | |||
tenPlus: string[10] | |||
tenTimes: string[10] | |||
hundred: string | |||
thousand: string | |||
kiloSpecialUnits: string[10] | |||
kiloUnits: string[10] | |||
kiloTens: string[10] | |||
kiloHundreds: string[10] | |||
kiloThousand: string | |||
kiloEvenSuffix: string | |||
kiloOddSuffix: string | |||
} |
@@ -0,0 +1,11 @@ | |||
export type Scale = 'long' | 'short' | |||
export interface ConvertOptions { | |||
scale?: Scale | |||
} | |||
export interface StreamOptions { | |||
encoding?: BufferEncoding | |||
} | |||
export type ReadStreamOptions = ConvertOptions & StreamOptions |
@@ -1,14 +0,0 @@ | |||
export default interface NumberSystemNameTable { | |||
units: string[10], | |||
tenPlus: string[10], | |||
tenTimes: string[10], | |||
hundred: string, | |||
thousand: string, | |||
kiloSpecialUnits: string[10], | |||
kiloUnits: string[10], | |||
kiloTens: string[10], | |||
kiloHundreds: string[10], | |||
kiloThousand: string, | |||
kiloEvenSuffix: string, | |||
kiloOddSuffix: string, | |||
} |
@@ -1,3 +1,3 @@ | |||
export default () => { | |||
throw Error('Not yet implemented!') | |||
} | |||
import Converter from './Converter' | |||
export default Converter |
@@ -23,6 +23,6 @@ test.each` | |||
${7} | ${'700'} | ${'siebenhundert'} | |||
${8} | ${'800'} | ${'achthundert'} | |||
${9} | ${'900'} | ${'neunhundert'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(hundredTimes(value)).toBe(name) | |||
}) |
@@ -9,13 +9,6 @@ interface HundredTimes { | |||
* @param {number} x100 - The number in the hundreds place. | |||
* @returns {string} The name of the number in the hundreds place. | |||
*/ | |||
const hundredTimes: HundredTimes = (x100) => ( | |||
x100 === 0 | |||
? NAMES.units[0] | |||
: [ | |||
NAMES.units[x100], | |||
NAMES.hundred, | |||
].join('') | |||
) | |||
const hundredTimes: HundredTimes = (x100) => (x100 === 0 ? NAMES.units[0] : [NAMES.units[x100], NAMES.hundred].join('')) | |||
export default hundredTimes |
@@ -25,7 +25,7 @@ describe('on 0 in hundreds place', () => { | |||
${7} | ${'7'} | ${'septi'} | |||
${8} | ${'8'} | ${'octi'} | |||
${9} | ${'9'} | ${'noni'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(combiningPrefix(0, 0, value)).toBe(name) | |||
}) | |||
}) | |||
@@ -41,7 +41,7 @@ describe('on 0 in hundreds place', () => { | |||
${7} | ${'septuaginti'} | |||
${8} | ${'octoginti'} | |||
${9} | ${'nonaginti'} | |||
`('on $tens in tens place', ({ tens, tensName, }) => { | |||
`('on $tens in tens place', ({ tens, tensName }) => { | |||
test.each` | |||
ones | display | |||
${0} | ${tensName} | |||
@@ -54,7 +54,7 @@ describe('on 0 in hundreds place', () => { | |||
${7} | ${'septen' + tensName} | |||
${8} | ${'octo' + tensName} | |||
${9} | ${'novem' + tensName} | |||
`(`should return "$display" for ${tens}$ones`, ({ ones, display, }) => { | |||
`(`should return "$display" for ${tens}$ones`, ({ ones, display }) => { | |||
expect(combiningPrefix(0, tens, ones)).toBe(display) | |||
}) | |||
}) | |||
@@ -71,7 +71,7 @@ describe.each` | |||
${7} | ${'septingen'} | |||
${8} | ${'octingen'} | |||
${9} | ${'nongen'} | |||
`('on $hundreds in hundreds place', ({ hundreds, hundredsName, }) => { | |||
`('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => { | |||
describe.each` | |||
tens | tensName | |||
${0} | ${'ti'} | |||
@@ -84,7 +84,7 @@ describe.each` | |||
${7} | ${'septuaginti'} | |||
${8} | ${'octoginti'} | |||
${9} | ${'nonaginti'} | |||
`('on $tens in tens place', ({ tens, tensName, }) => { | |||
`('on $tens in tens place', ({ tens, tensName }) => { | |||
test.each` | |||
ones | display | |||
${0} | ${hundredsName + tensName} | |||
@@ -97,7 +97,7 @@ describe.each` | |||
${7} | ${hundredsName + 'septen' + tensName} | |||
${8} | ${hundredsName + 'octo' + tensName} | |||
${9} | ${hundredsName + 'novem' + tensName} | |||
`(`should return "$display" for ${hundreds}${tens}$ones`, ({ ones, display, }) => { | |||
`(`should return "$display" for ${hundreds}${tens}$ones`, ({ ones, display }) => { | |||
expect(combiningPrefix(hundreds, tens, ones)).toBe(display) | |||
}) | |||
}) | |||
@@ -114,7 +114,7 @@ describe.each` | |||
${7} | ${'septingen'} | |||
${8} | ${'octingen'} | |||
${9} | ${'nongen'} | |||
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName, }) => { | |||
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName }) => { | |||
describe.each` | |||
tenThousands | tenThousandsName | |||
${0} | ${''} | |||
@@ -127,7 +127,7 @@ describe.each` | |||
${7} | ${'septuagin'} | |||
${8} | ${'octogin'} | |||
${9} | ${'nonagin'} | |||
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName, }) => { | |||
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName }) => { | |||
test.each` | |||
thousands | display | name | |||
${0} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milliati'} | |||
@@ -140,17 +140,9 @@ describe.each` | |||
${7000} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milliati'} | |||
${8000} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'octo' + tenThousandsName + 'milliati'} | |||
${9000} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'novem' + tenThousandsName + 'milliati'} | |||
`(`should return "$name" for $display`, ({ thousands, name, }) => { | |||
const kiloHundreds = ( | |||
hundredThousands * 1000 | |||
+ tenThousands * 100 | |||
+ thousands / 100 | |||
) | |||
expect(combiningPrefix( | |||
kiloHundreds, | |||
0, | |||
0, | |||
)).toBe(name) | |||
`(`should return "$name" for $display`, ({ thousands, name }) => { | |||
const kiloHundreds = hundredThousands * 1000 + tenThousands * 100 + thousands / 100 | |||
expect(combiningPrefix(kiloHundreds, 0, 0)).toBe(name) | |||
}) | |||
}) | |||
}) | |||
@@ -166,7 +158,7 @@ test.each` | |||
${7} | ${'7000000'} | ${'septenmilliamilliati'} | |||
${8} | ${'8000000'} | ${'octomilliamilliati'} | |||
${9} | ${'9000000'} | ${'novemmilliamilliati'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(combiningPrefix(value * 10000, 0, 0)).toBe(name) | |||
}) | |||
@@ -181,7 +173,6 @@ test.each` | |||
${7} | ${'7007000'} | ${'septenmilliamilliaseptenmilliati'} | |||
${8} | ${'8008000'} | ${'octomilliamilliaoctomilliati'} | |||
${9} | ${'9009000'} | ${'novemmilliamillianovemmilliati'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(combiningPrefix(value * 10010, 0, 0)).toBe(name) | |||
}) | |||
@@ -4,20 +4,10 @@ import tens from './tens' | |||
import hundreds from './hundreds' | |||
interface CombiningPrefix { | |||
( | |||
kiloHundreds: number, | |||
kiloTens: number, | |||
kiloOnes: number, | |||
kiloPower?: number, | |||
): string, | |||
(kiloHundreds: number, kiloTens: number, kiloOnes: number, kiloPower?: number): string | |||
} | |||
const combiningPrefix: CombiningPrefix = ( | |||
kiloHundredsRaw, | |||
kiloTens, | |||
kiloOnes, | |||
kiloPower = 0, | |||
) => { | |||
const combiningPrefix: CombiningPrefix = (kiloHundredsRaw, kiloTens, kiloOnes, kiloPower = 0) => { | |||
let kiloHundreds = kiloHundredsRaw | |||
let prefix = '' | |||
@@ -25,8 +15,8 @@ const combiningPrefix: CombiningPrefix = ( | |||
if (isMillia) { | |||
prefix += combiningPrefix( | |||
Math.floor(kiloHundredsRaw / 1000), | |||
Math.floor(kiloHundredsRaw / 100 % 10), | |||
Math.floor(kiloHundredsRaw / 10 % 10), | |||
Math.floor((kiloHundredsRaw / 100) % 10), | |||
Math.floor((kiloHundredsRaw / 10) % 10), | |||
kiloPower + 1, | |||
) | |||
kiloHundreds = kiloHundredsRaw % 10 | |||
@@ -38,43 +28,18 @@ const combiningPrefix: CombiningPrefix = ( | |||
} | |||
if ( | |||
( | |||
kiloPower > 0 | |||
&& ( | |||
( | |||
kiloHundreds === 0 | |||
&& kiloTens === 0 | |||
&& kiloOnes > 1 | |||
) | |||
|| ( | |||
( | |||
kiloHundreds > 0 | |||
|| kiloTens > 0 | |||
) | |||
&& kiloOnes > 0 | |||
) | |||
|| ( | |||
kiloHundreds === 0 | |||
&& kiloTens === 0 | |||
&& kiloOnes === 1 | |||
&& prefix.endsWith(NAMES.kiloThousand) | |||
) | |||
) | |||
) | |||
kiloPower > 0 && | |||
((kiloHundreds === 0 && kiloTens === 0 && kiloOnes > 1) || | |||
((kiloHundreds > 0 || kiloTens > 0) && kiloOnes > 0) || | |||
(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 1 && prefix.endsWith(NAMES.kiloThousand))) | |||
) { | |||
// http://www.isthe.com/chongo/tech/math/number/howhigh.html | |||
// Section: Titanic size numbers < 10^3000003 | |||
prefix += ones( | |||
kiloOnes, | |||
false | |||
) | |||
prefix += ones(kiloOnes, false) | |||
} | |||
if (kiloPower === 0 && kiloOnes > 0) { | |||
const special = kiloHundreds === 0 && kiloTens === 0 | |||
prefix += ones( | |||
kiloOnes, | |||
special | |||
) | |||
prefix += ones(kiloOnes, special) | |||
if (special && [5, 6].includes(kiloOnes)) { | |||
prefix += 't' | |||
} | |||
@@ -84,11 +49,7 @@ const combiningPrefix: CombiningPrefix = ( | |||
} | |||
if (kiloPower > 0) { | |||
if (!( | |||
kiloHundreds === 0 | |||
&& kiloTens === 0 | |||
&& kiloOnes === 0 | |||
)) { | |||
if (!(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 0)) { | |||
for (let p = 0; p < kiloPower; p += 1) { | |||
prefix += NAMES.kiloThousand | |||
} | |||
@@ -96,11 +57,7 @@ const combiningPrefix: CombiningPrefix = ( | |||
return prefix | |||
} | |||
if ( | |||
(kiloHundreds === 0 && kiloTens > 1) | |||
|| (kiloHundreds > 0 && kiloTens !== 1) | |||
|| kiloHundredsRaw >= 10 | |||
) { | |||
if ((kiloHundreds === 0 && kiloTens > 1) || (kiloHundreds > 0 && kiloTens !== 1) || kiloHundredsRaw >= 10) { | |||
prefix += 't' | |||
} | |||
return prefix + 'i' | |||
@@ -23,6 +23,6 @@ test.each` | |||
${7} | ${'700'} | ${'septingen'} | |||
${8} | ${'800'} | ${'octingen'} | |||
${9} | ${'900'} | ${'nongen'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(hundreds(value)).toBe(name) | |||
}) |
@@ -1,7 +1,7 @@ | |||
import NAMES from '../../names.json' | |||
interface Hundreds { | |||
(kiloHundreds: number): string, | |||
(kiloHundreds: number): string | |||
} | |||
const hundreds: Hundreds = (kiloHundreds) => NAMES.kiloHundreds[kiloHundreds] | |||
@@ -25,7 +25,7 @@ describe('on ordinary units', () => { | |||
${7} | ${'7'} | ${'septen'} | |||
${8} | ${'8'} | ${'octo'} | |||
${9} | ${'9'} | ${'novem'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(ones(value, false)).toBe(name) | |||
}) | |||
}) | |||
@@ -43,7 +43,7 @@ describe('on special units', () => { | |||
${7} | ${'7'} | ${'sept'} | |||
${8} | ${'8'} | ${'oct'} | |||
${9} | ${'9'} | ${'non'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(ones(value, true)).toBe(name) | |||
}) | |||
}) |
@@ -1,13 +1,10 @@ | |||
import NAMES from '../../names.json' | |||
interface Ones { | |||
(kiloOnes: number, special: boolean): string, | |||
(kiloOnes: number, special: boolean): string | |||
} | |||
const ones: Ones = (kiloOnes, special = false) => ( | |||
special | |||
? NAMES.kiloSpecialUnits[kiloOnes] | |||
: NAMES.kiloUnits[kiloOnes] | |||
) | |||
const ones: Ones = (kiloOnes, special = false) => | |||
special ? NAMES.kiloSpecialUnits[kiloOnes] : NAMES.kiloUnits[kiloOnes] | |||
export default ones |
@@ -23,6 +23,6 @@ test.each` | |||
${7} | ${'70'} | ${'septuagin'} | |||
${8} | ${'80'} | ${'octogin'} | |||
${9} | ${'90'} | ${'nonagin'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(tens(value)).toBe(name) | |||
}) |
@@ -1,7 +1,7 @@ | |||
import NAMES from '../../names.json' | |||
interface Tens { | |||
(kiloTens: number): string, | |||
(kiloTens: number): string | |||
} | |||
const tens: Tens = (kiloTens) => NAMES.kiloTens[kiloTens] | |||
@@ -24,7 +24,6 @@ test.each` | |||
${7} | ${'7'} | ${'sieben'} | |||
${8} | ${'8'} | ${'acht'} | |||
${9} | ${'9'} | ${'neun'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(ones(value)).toBe(name) | |||
}) | |||
@@ -24,6 +24,6 @@ test.each` | |||
${7} | ${'17'} | ${'siebzehn'} | |||
${8} | ${'18'} | ${'achtzehn'} | |||
${9} | ${'19'} | ${'neunzehn'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(tenPlus(value)).toBe(name) | |||
}) |
@@ -23,6 +23,6 @@ test.each` | |||
${7} | ${'70'} | ${'siebzig'} | |||
${8} | ${'80'} | ${'achtzig'} | |||
${9} | ${'90'} | ${'neunzig'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(tenTimes(value)).toBe(name) | |||
}) |
@@ -25,7 +25,7 @@ describe('on 0 in tens place', () => { | |||
${7} | ${'sieben'} | |||
${8} | ${'acht'} | |||
${9} | ${'neun'} | |||
`(`should return "$onesName" for $ones`, ({ ones, onesName, }) => { | |||
`(`should return "$onesName" for $ones`, ({ ones, onesName }) => { | |||
expect(tensFn(0, ones)).toBe(onesName) | |||
}) | |||
}) | |||
@@ -43,35 +43,35 @@ describe('on 1 in tens place', () => { | |||
${7} | ${'siebzehn'} | |||
${8} | ${'achtzehn'} | |||
${9} | ${'neunzehn'} | |||
`(`should return "$tenPlusName" for 1$ones`, ({ ones, tenPlusName, }) => { | |||
`(`should return "$tenPlusName" for 1$ones`, ({ ones, tenPlusName }) => { | |||
expect(tensFn(1, ones)).toBe(tenPlusName) | |||
}) | |||
}) | |||
describe.each` | |||
tens | tensName | |||
${2} | ${'zwanzig'} | |||
${3} | ${'dreißig'} | |||
${4} | ${'vierzig'} | |||
${5} | ${'fünfzig'} | |||
${6} | ${'sechzig'} | |||
${7} | ${'siebzig'} | |||
${8} | ${'achtzig'} | |||
${9} | ${'neunzig'} | |||
`('on $tens in tens place', ({ tens, tensName, }) => { | |||
tens | tensName | |||
${2} | ${'zwanzig'} | |||
${3} | ${'dreißig'} | |||
${4} | ${'vierzig'} | |||
${5} | ${'fünfzig'} | |||
${6} | ${'sechzig'} | |||
${7} | ${'siebzig'} | |||
${8} | ${'achtzig'} | |||
${9} | ${'neunzig'} | |||
`('on $tens in tens place', ({ tens, tensName }) => { | |||
test.each` | |||
ones | display | |||
${0} | ${'' + tensName} | |||
${1} | ${'einund' + tensName} | |||
${2} | ${'zweiund' + tensName} | |||
${3} | ${'dreiund' + tensName} | |||
${4} | ${'vierund' + tensName} | |||
${5} | ${'fünfund' + tensName} | |||
${6} | ${'sechsund' + tensName} | |||
${7} | ${'siebenund' + tensName} | |||
${8} | ${'achtund' + tensName} | |||
${9} | ${'neunund' + tensName} | |||
`(`should return "$display" for ${tens}$ones`, ({ ones, display, }) => { | |||
ones | display | |||
${0} | ${'' + tensName} | |||
${1} | ${'einund' + tensName} | |||
${2} | ${'zweiund' + tensName} | |||
${3} | ${'dreiund' + tensName} | |||
${4} | ${'vierund' + tensName} | |||
${5} | ${'fünfund' + tensName} | |||
${6} | ${'sechsund' + tensName} | |||
${7} | ${'siebenund' + tensName} | |||
${8} | ${'achtund' + tensName} | |||
${9} | ${'neunund' + tensName} | |||
`(`should return "$display" for ${tens}$ones`, ({ ones, display }) => { | |||
expect(tensFn(tens, ones)).toBe(display) | |||
}) | |||
}) |
@@ -4,7 +4,7 @@ import tenPlus from '../base/tenPlus' | |||
import getBaseTenTimesName from '../base/tenTimes' | |||
interface Tens { | |||
(x10: number, x1: number): string, | |||
(x10: number, x1: number): string | |||
} | |||
const tens: Tens = (x10, x1) => { | |||
@@ -20,16 +20,7 @@ const tens: Tens = (x10, x1) => { | |||
break | |||
} | |||
return ( | |||
x1 > 0 | |||
? [ | |||
ones(x1), | |||
NAMES.and, | |||
getBaseTenTimesName(x10), | |||
] | |||
.join('') | |||
: getBaseTenTimesName(x10) | |||
) | |||
return x1 > 0 ? [ones(x1), NAMES.and, getBaseTenTimesName(x10)].join('') : getBaseTenTimesName(x10) | |||
} | |||
export default tens |
@@ -34,7 +34,7 @@ test.each` | |||
${17} | ${'Octilliard'} | |||
${18} | ${'Nonillion'} | |||
${19} | ${'Nonilliard'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -49,7 +49,7 @@ test.each` | |||
${140} | ${'Septuagintillion'} | |||
${160} | ${'Octogintillion'} | |||
${180} | ${'Nonagintillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -64,7 +64,7 @@ test.each` | |||
${1400} | ${'Septingentillion'} | |||
${1600} | ${'Octingentillion'} | |||
${1800} | ${'Nongentillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -79,7 +79,7 @@ test.each` | |||
${14000} | ${'Septenmilliatillion'} | |||
${16000} | ${'Octomilliatillion'} | |||
${18000} | ${'Novemmilliatillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -94,7 +94,7 @@ test.each` | |||
${140000} | ${'Septuaginmilliatillion'} | |||
${160000} | ${'Octoginmilliatillion'} | |||
${180000} | ${'Nonaginmilliatillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -109,7 +109,7 @@ test.each` | |||
${1400000} | ${'Septingenmilliatillion'} | |||
${1600000} | ${'Octingenmilliatillion'} | |||
${1800000} | ${'Nongenmilliatillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -124,6 +124,6 @@ test.each` | |||
${14000000} | ${'Septenmilliamilliatillion'} | |||
${16000000} | ${'Octomilliamilliatillion'} | |||
${18000000} | ${'Novemmilliamilliatillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) |
@@ -1,12 +1,10 @@ | |||
import { GetKiloName, } from '../../common/NumberSystem' | |||
import { GetKiloName } from '../../NumberSystem' | |||
import NAMES from './names.json' | |||
import getKiloCombiningPrefix from './base/kilo/combiningPrefix' | |||
const capitalizeFirstLetter = (word: string) => ( | |||
word.slice(0, 1).toUpperCase() + word.slice(1) | |||
) | |||
const capitalizeFirstLetter = (word: string) => word.slice(0, 1).toUpperCase() + word.slice(1) | |||
const getLongKiloName: GetKiloName = thousandPower => { | |||
const getLongKiloName: GetKiloName = (thousandPower) => { | |||
if (thousandPower === 0) { | |||
return '' | |||
} | |||
@@ -15,18 +13,12 @@ const getLongKiloName: GetKiloName = thousandPower => { | |||
} | |||
const kilo = thousandPower | |||
const kiloHundreds = Math.floor(kilo / 2 / 100) | |||
const kiloTens = Math.floor(kilo / 2 / 10 % 10) | |||
const kiloOnes = Math.floor(kilo / 2 % 10) | |||
const kiloCombiningPrefix = getKiloCombiningPrefix( | |||
kiloHundreds, | |||
kiloTens, | |||
kiloOnes | |||
) | |||
const kiloTens = Math.floor((kilo / 2 / 10) % 10) | |||
const kiloOnes = Math.floor((kilo / 2) % 10) | |||
const kiloCombiningPrefix = getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes) | |||
return capitalizeFirstLetter( | |||
thousandPower % 2 === 0 | |||
? kiloCombiningPrefix + NAMES.kiloEvenSuffix | |||
: kiloCombiningPrefix + NAMES.kiloOddSuffix | |||
thousandPower % 2 === 0 ? kiloCombiningPrefix + NAMES.kiloEvenSuffix : kiloCombiningPrefix + NAMES.kiloOddSuffix, | |||
) | |||
} | |||
@@ -1,4 +1,4 @@ | |||
import NumberSystem from '../common/NumberSystem' | |||
import NumberSystem from '../NumberSystem' | |||
import getKiloCount from './en/getKiloCount' | |||
import getLongKiloName from './en/getLongKiloName' | |||
import getShortKiloName from './en/getShortKiloName' | |||
@@ -8,7 +8,7 @@ const en: NumberSystem = { | |||
getKiloName: { | |||
short: getShortKiloName, | |||
long: getLongKiloName, | |||
} | |||
}, | |||
} | |||
export default en |
@@ -23,6 +23,6 @@ test.each` | |||
${7} | ${'700'} | ${'seven hundred'} | |||
${8} | ${'800'} | ${'eight hundred'} | |||
${9} | ${'900'} | ${'nine hundred'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(hundredTimes(value)).toBe(name) | |||
}) |
@@ -9,13 +9,7 @@ interface HundredTimes { | |||
* @param {number} x100 - The number in the hundreds place. | |||
* @returns {string} The name of the number in the hundreds place. | |||
*/ | |||
const hundredTimes: HundredTimes = (x100) => ( | |||
x100 === 0 | |||
? NAMES.units[0] | |||
: [ | |||
NAMES.units[x100], | |||
NAMES.hundred, | |||
].join(' ') | |||
) | |||
const hundredTimes: HundredTimes = (x100) => | |||
x100 === 0 ? NAMES.units[0] : [NAMES.units[x100], NAMES.hundred].join(' ') | |||
export default hundredTimes |
@@ -25,7 +25,7 @@ describe('on 0 in hundreds place', () => { | |||
${7} | ${'7'} | ${'septi'} | |||
${8} | ${'8'} | ${'octi'} | |||
${9} | ${'9'} | ${'noni'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(combiningPrefix(0, 0, value)).toBe(name) | |||
}) | |||
}) | |||
@@ -41,7 +41,7 @@ describe('on 0 in hundreds place', () => { | |||
${7} | ${'septuaginti'} | |||
${8} | ${'octoginti'} | |||
${9} | ${'nonaginti'} | |||
`('on $tens in tens place', ({ tens, tensName, }) => { | |||
`('on $tens in tens place', ({ tens, tensName }) => { | |||
test.each` | |||
ones | display | |||
${0} | ${tensName} | |||
@@ -54,7 +54,7 @@ describe('on 0 in hundreds place', () => { | |||
${7} | ${'septen' + tensName} | |||
${8} | ${'octo' + tensName} | |||
${9} | ${'novem' + tensName} | |||
`(`should return "$display" for ${tens}$ones`, ({ ones, display, }) => { | |||
`(`should return "$display" for ${tens}$ones`, ({ ones, display }) => { | |||
expect(combiningPrefix(0, tens, ones)).toBe(display) | |||
}) | |||
}) | |||
@@ -71,7 +71,7 @@ describe.each` | |||
${7} | ${'septingen'} | |||
${8} | ${'octingen'} | |||
${9} | ${'nongen'} | |||
`('on $hundreds in hundreds place', ({ hundreds, hundredsName, }) => { | |||
`('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => { | |||
describe.each` | |||
tens | tensName | |||
${0} | ${'ti'} | |||
@@ -84,7 +84,7 @@ describe.each` | |||
${7} | ${'septuaginti'} | |||
${8} | ${'octoginti'} | |||
${9} | ${'nonaginti'} | |||
`('on $tens in tens place', ({ tens, tensName, }) => { | |||
`('on $tens in tens place', ({ tens, tensName }) => { | |||
test.each` | |||
ones | display | |||
${0} | ${hundredsName + tensName} | |||
@@ -97,7 +97,7 @@ describe.each` | |||
${7} | ${hundredsName + 'septen' + tensName} | |||
${8} | ${hundredsName + 'octo' + tensName} | |||
${9} | ${hundredsName + 'novem' + tensName} | |||
`(`should return "$display" for ${hundreds}${tens}$ones`, ({ ones, display, }) => { | |||
`(`should return "$display" for ${hundreds}${tens}$ones`, ({ ones, display }) => { | |||
expect(combiningPrefix(hundreds, tens, ones)).toBe(display) | |||
}) | |||
}) | |||
@@ -114,7 +114,7 @@ describe.each` | |||
${7} | ${'septingen'} | |||
${8} | ${'octingen'} | |||
${9} | ${'nongen'} | |||
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName, }) => { | |||
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName }) => { | |||
describe.each` | |||
tenThousands | tenThousandsName | |||
${0} | ${''} | |||
@@ -127,7 +127,7 @@ describe.each` | |||
${7} | ${'septuagin'} | |||
${8} | ${'octogin'} | |||
${9} | ${'nonagin'} | |||
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName, }) => { | |||
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName }) => { | |||
test.each` | |||
thousands | display | name | |||
${0} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milliati'} | |||
@@ -140,17 +140,9 @@ describe.each` | |||
${7000} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milliati'} | |||
${8000} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'octo' + tenThousandsName + 'milliati'} | |||
${9000} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'novem' + tenThousandsName + 'milliati'} | |||
`(`should return "$name" for $display`, ({ thousands, name, }) => { | |||
const kiloHundreds = ( | |||
hundredThousands * 1000 | |||
+ tenThousands * 100 | |||
+ thousands / 100 | |||
) | |||
expect(combiningPrefix( | |||
kiloHundreds, | |||
0, | |||
0, | |||
)).toBe(name) | |||
`(`should return "$name" for $display`, ({ thousands, name }) => { | |||
const kiloHundreds = hundredThousands * 1000 + tenThousands * 100 + thousands / 100 | |||
expect(combiningPrefix(kiloHundreds, 0, 0)).toBe(name) | |||
}) | |||
}) | |||
}) | |||
@@ -166,7 +158,7 @@ test.each` | |||
${7} | ${'7000000'} | ${'septenmilliamilliati'} | |||
${8} | ${'8000000'} | ${'octomilliamilliati'} | |||
${9} | ${'9000000'} | ${'novemmilliamilliati'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(combiningPrefix(value * 10000, 0, 0)).toBe(name) | |||
}) | |||
@@ -181,7 +173,6 @@ test.each` | |||
${7} | ${'7007000'} | ${'septenmilliamilliaseptenmilliati'} | |||
${8} | ${'8008000'} | ${'octomilliamilliaoctomilliati'} | |||
${9} | ${'9009000'} | ${'novemmilliamillianovemmilliati'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(combiningPrefix(value * 10010, 0, 0)).toBe(name) | |||
}) | |||
@@ -4,20 +4,10 @@ import tens from './tens' | |||
import hundreds from './hundreds' | |||
interface CombiningPrefix { | |||
( | |||
kiloHundreds: number, | |||
kiloTens: number, | |||
kiloOnes: number, | |||
kiloPower?: number, | |||
): string, | |||
(kiloHundreds: number, kiloTens: number, kiloOnes: number, kiloPower?: number): string | |||
} | |||
const combiningPrefix: CombiningPrefix = ( | |||
kiloHundredsRaw, | |||
kiloTens, | |||
kiloOnes, | |||
kiloPower = 0, | |||
) => { | |||
const combiningPrefix: CombiningPrefix = (kiloHundredsRaw, kiloTens, kiloOnes, kiloPower = 0) => { | |||
let kiloHundreds = kiloHundredsRaw | |||
let prefix = '' | |||
@@ -25,8 +15,8 @@ const combiningPrefix: CombiningPrefix = ( | |||
if (isMillia) { | |||
prefix += combiningPrefix( | |||
Math.floor(kiloHundredsRaw / 1000), | |||
Math.floor(kiloHundredsRaw / 100 % 10), | |||
Math.floor(kiloHundredsRaw / 10 % 10), | |||
Math.floor((kiloHundredsRaw / 100) % 10), | |||
Math.floor((kiloHundredsRaw / 10) % 10), | |||
kiloPower + 1, | |||
) | |||
kiloHundreds = kiloHundredsRaw % 10 | |||
@@ -38,43 +28,18 @@ const combiningPrefix: CombiningPrefix = ( | |||
} | |||
if ( | |||
( | |||
kiloPower > 0 | |||
&& ( | |||
( | |||
kiloHundreds === 0 | |||
&& kiloTens === 0 | |||
&& kiloOnes > 1 | |||
) | |||
|| ( | |||
( | |||
kiloHundreds > 0 | |||
|| kiloTens > 0 | |||
) | |||
&& kiloOnes > 0 | |||
) | |||
|| ( | |||
kiloHundreds === 0 | |||
&& kiloTens === 0 | |||
&& kiloOnes === 1 | |||
&& prefix.endsWith(NAMES.kiloThousand) | |||
) | |||
) | |||
) | |||
kiloPower > 0 && | |||
((kiloHundreds === 0 && kiloTens === 0 && kiloOnes > 1) || | |||
((kiloHundreds > 0 || kiloTens > 0) && kiloOnes > 0) || | |||
(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 1 && prefix.endsWith(NAMES.kiloThousand))) | |||
) { | |||
// http://www.isthe.com/chongo/tech/math/number/howhigh.html | |||
// Section: Titanic size numbers < 10^3000003 | |||
prefix += ones( | |||
kiloOnes, | |||
false | |||
) | |||
prefix += ones(kiloOnes, false) | |||
} | |||
if (kiloPower === 0 && kiloOnes > 0) { | |||
const special = kiloHundreds === 0 && kiloTens === 0 | |||
prefix += ones( | |||
kiloOnes, | |||
special | |||
) | |||
prefix += ones(kiloOnes, special) | |||
if (special && [5, 6].includes(kiloOnes)) { | |||
prefix += 't' | |||
} | |||
@@ -84,11 +49,7 @@ const combiningPrefix: CombiningPrefix = ( | |||
} | |||
if (kiloPower > 0) { | |||
if (!( | |||
kiloHundreds === 0 | |||
&& kiloTens === 0 | |||
&& kiloOnes === 0 | |||
)) { | |||
if (!(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 0)) { | |||
for (let p = 0; p < kiloPower; p += 1) { | |||
prefix += NAMES.kiloThousand | |||
} | |||
@@ -96,11 +57,7 @@ const combiningPrefix: CombiningPrefix = ( | |||
return prefix | |||
} | |||
if ( | |||
(kiloHundreds === 0 && kiloTens > 1) | |||
|| (kiloHundreds > 0 && kiloTens !== 1) | |||
|| kiloHundredsRaw >= 10 | |||
) { | |||
if ((kiloHundreds === 0 && kiloTens > 1) || (kiloHundreds > 0 && kiloTens !== 1) || kiloHundredsRaw >= 10) { | |||
prefix += 't' | |||
} | |||
return prefix + 'i' | |||
@@ -23,6 +23,6 @@ test.each` | |||
${7} | ${'700'} | ${'septingen'} | |||
${8} | ${'800'} | ${'octingen'} | |||
${9} | ${'900'} | ${'nongen'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(hundreds(value)).toBe(name) | |||
}) |
@@ -1,7 +1,7 @@ | |||
import NAMES from '../../names.json' | |||
interface Hundreds { | |||
(kiloHundreds: number): string, | |||
(kiloHundreds: number): string | |||
} | |||
const hundreds: Hundreds = (kiloHundreds) => NAMES.kiloHundreds[kiloHundreds] | |||
@@ -25,7 +25,7 @@ describe('on ordinary units', () => { | |||
${7} | ${'7'} | ${'septen'} | |||
${8} | ${'8'} | ${'octo'} | |||
${9} | ${'9'} | ${'novem'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(ones(value, false)).toBe(name) | |||
}) | |||
}) | |||
@@ -43,7 +43,7 @@ describe('on special units', () => { | |||
${7} | ${'7'} | ${'sept'} | |||
${8} | ${'8'} | ${'oct'} | |||
${9} | ${'9'} | ${'non'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(ones(value, true)).toBe(name) | |||
}) | |||
}) |
@@ -1,13 +1,10 @@ | |||
import NAMES from '../../names.json' | |||
interface Ones { | |||
(kiloOnes: number, special: boolean): string, | |||
(kiloOnes: number, special: boolean): string | |||
} | |||
const ones: Ones = (kiloOnes, special = false) => ( | |||
special | |||
? NAMES.kiloSpecialUnits[kiloOnes] | |||
: NAMES.kiloUnits[kiloOnes] | |||
) | |||
const ones: Ones = (kiloOnes, special = false) => | |||
special ? NAMES.kiloSpecialUnits[kiloOnes] : NAMES.kiloUnits[kiloOnes] | |||
export default ones |
@@ -23,6 +23,6 @@ test.each` | |||
${7} | ${'70'} | ${'septuagin'} | |||
${8} | ${'80'} | ${'octogin'} | |||
${9} | ${'90'} | ${'nonagin'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(tens(value)).toBe(name) | |||
}) |
@@ -1,7 +1,7 @@ | |||
import NAMES from '../../names.json' | |||
interface Tens { | |||
(kiloTens: number): string, | |||
(kiloTens: number): string | |||
} | |||
const tens: Tens = (kiloTens) => NAMES.kiloTens[kiloTens] | |||
@@ -24,7 +24,6 @@ test.each` | |||
${7} | ${'7'} | ${'seven'} | |||
${8} | ${'8'} | ${'eight'} | |||
${9} | ${'9'} | ${'nine'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(ones(value)).toBe(name) | |||
}) | |||
@@ -24,6 +24,6 @@ test.each` | |||
${7} | ${'17'} | ${'seventeen'} | |||
${8} | ${'18'} | ${'eighteen'} | |||
${9} | ${'19'} | ${'nineteen'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(tenPlus(value)).toBe(name) | |||
}) |
@@ -23,6 +23,6 @@ test.each` | |||
${7} | ${'70'} | ${'seventy'} | |||
${8} | ${'80'} | ${'eighty'} | |||
${9} | ${'90'} | ${'ninety'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(tenTimes(value)).toBe(name) | |||
}) |
@@ -25,7 +25,7 @@ describe('on 0 in tens place', () => { | |||
${7} | ${'seven'} | |||
${8} | ${'eight'} | |||
${9} | ${'nine'} | |||
`(`should return "$onesName" for $ones`, ({ ones, onesName, }) => { | |||
`(`should return "$onesName" for $ones`, ({ ones, onesName }) => { | |||
expect(tensFn(0, ones)).toBe(onesName) | |||
}) | |||
}) | |||
@@ -43,38 +43,35 @@ describe('on 1 in tens place', () => { | |||
${7} | ${'seventeen'} | |||
${8} | ${'eighteen'} | |||
${9} | ${'nineteen'} | |||
`(`should return "$tenPlusName" for 1$ones`, ({ ones, tenPlusName, }) => { | |||
`(`should return "$tenPlusName" for 1$ones`, ({ ones, tenPlusName }) => { | |||
expect(tensFn(1, ones)).toBe(tenPlusName) | |||
}) | |||
}) | |||
describe.each` | |||
tens | tensName | |||
${2} | ${'twenty'} | |||
${3} | ${'thirty'} | |||
${4} | ${'forty'} | |||
${5} | ${'fifty'} | |||
${6} | ${'sixty'} | |||
${7} | ${'seventy'} | |||
${8} | ${'eighty'} | |||
${9} | ${'ninety'} | |||
`('on $tens in tens place', ({ tens, tensName, }) => { | |||
tens | tensName | |||
${2} | ${'twenty'} | |||
${3} | ${'thirty'} | |||
${4} | ${'forty'} | |||
${5} | ${'fifty'} | |||
${6} | ${'sixty'} | |||
${7} | ${'seventy'} | |||
${8} | ${'eighty'} | |||
${9} | ${'ninety'} | |||
`('on $tens in tens place', ({ tens, tensName }) => { | |||
test.each` | |||
ones | onesName | |||
${0} | ${''} | |||
${1} | ${' one'} | |||
${2} | ${' two'} | |||
${3} | ${' three'} | |||
${4} | ${' four'} | |||
${5} | ${' five'} | |||
${6} | ${' six'} | |||
${7} | ${' seven'} | |||
${8} | ${' eight'} | |||
${9} | ${' nine'} | |||
`(`should return "${tensName}$onesName" for ${tens}$ones`, ({ ones, onesName, }) => { | |||
expect(tensFn(tens, ones)).toBe([ | |||
tensName, | |||
onesName | |||
].join('')) | |||
ones | onesName | |||
${0} | ${''} | |||
${1} | ${' one'} | |||
${2} | ${' two'} | |||
${3} | ${' three'} | |||
${4} | ${' four'} | |||
${5} | ${' five'} | |||
${6} | ${' six'} | |||
${7} | ${' seven'} | |||
${8} | ${' eight'} | |||
${9} | ${' nine'} | |||
`(`should return "${tensName}$onesName" for ${tens}$ones`, ({ ones, onesName }) => { | |||
expect(tensFn(tens, ones)).toBe([tensName, onesName].join('')) | |||
}) | |||
}) |
@@ -3,7 +3,7 @@ import tenPlus from '../base/tenPlus' | |||
import getBaseTenTimesName from '../base/tenTimes' | |||
interface Tens { | |||
(x10: number, x1: number): string, | |||
(x10: number, x1: number): string | |||
} | |||
const tens: Tens = (x10, x1) => { | |||
@@ -19,15 +19,7 @@ const tens: Tens = (x10, x1) => { | |||
break | |||
} | |||
return ( | |||
x1 > 0 | |||
? [ | |||
getBaseTenTimesName(x10), | |||
ones(x1), | |||
] | |||
.join(' ') | |||
: getBaseTenTimesName(x10) | |||
) | |||
return x1 > 0 ? [getBaseTenTimesName(x10), ones(x1)].join(' ') : getBaseTenTimesName(x10) | |||
} | |||
export default tens |
@@ -23,7 +23,7 @@ describe.each` | |||
${7} | ${'seven hundred'} | |||
${8} | ${'eight hundred'} | |||
${9} | ${'nine hundred'} | |||
`('on $hundreds in hundreds place', ({ hundreds, hundredsName, }) => { | |||
`('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => { | |||
describe('on 0 in tens place', () => { | |||
test.each` | |||
ones | onesName | |||
@@ -37,13 +37,10 @@ describe.each` | |||
${7} | ${' seven'} | |||
${8} | ${' eight'} | |||
${9} | ${' nine'} | |||
`(`should return "${hundredsName}$onesName" for ${hundreds}0$ones`, ({ ones, onesName, }) => { | |||
expect(getKiloCount(hundreds, 0, ones)).toBe([ | |||
hundredsName, | |||
onesName | |||
].join('')) | |||
}) | |||
`(`should return "${hundredsName}$onesName" for ${hundreds}0$ones`, ({ ones, onesName }) => { | |||
expect(getKiloCount(hundreds, 0, ones)).toBe([hundredsName, onesName].join('')) | |||
}) | |||
}) | |||
describe('on 1 in tens place', () => { | |||
test.each` | |||
@@ -58,13 +55,10 @@ describe.each` | |||
${7} | ${' seventeen'} | |||
${8} | ${' eighteen'} | |||
${9} | ${' nineteen'} | |||
`(`should return "${hundredsName}$tenPlusName" for ${hundreds}1$ones`, ({ ones, tenPlusName, }) => { | |||
expect(getKiloCount(hundreds, 1, ones)).toBe([ | |||
hundredsName, | |||
tenPlusName | |||
].join('')) | |||
}) | |||
`(`should return "${hundredsName}$tenPlusName" for ${hundreds}1$ones`, ({ ones, tenPlusName }) => { | |||
expect(getKiloCount(hundreds, 1, ones)).toBe([hundredsName, tenPlusName].join('')) | |||
}) | |||
}) | |||
describe.each` | |||
tens | tensName | |||
@@ -76,7 +70,7 @@ describe.each` | |||
${7} | ${' seventy'} | |||
${8} | ${' eighty'} | |||
${9} | ${' ninety'} | |||
`('on $tens in tens place', ({ tens, tensName, }) => { | |||
`('on $tens in tens place', ({ tens, tensName }) => { | |||
test.each` | |||
ones | onesName | |||
${0} | ${''} | |||
@@ -89,12 +83,8 @@ describe.each` | |||
${7} | ${' seven'} | |||
${8} | ${' eight'} | |||
${9} | ${' nine'} | |||
`(`should return "${hundredsName}${tensName}$onesName" for ${hundreds}${tens}$ones`, ({ ones, onesName, }) => { | |||
expect(getKiloCount(hundreds, tens, ones)).toBe([ | |||
hundredsName, | |||
tensName, | |||
onesName | |||
].join('')) | |||
`(`should return "${hundredsName}${tensName}$onesName" for ${hundreds}${tens}$ones`, ({ ones, onesName }) => { | |||
expect(getKiloCount(hundreds, tens, ones)).toBe([hundredsName, tensName, onesName].join('')) | |||
}) | |||
}) | |||
}) |
@@ -1,12 +1,8 @@ | |||
import { GetKiloCount, } from '../../common/NumberSystem' | |||
import { GetKiloCount } from '../../NumberSystem' | |||
import constructTens from './construct/tens' | |||
import hundredTimes from './base/hundredTimes' | |||
const getKiloCount: GetKiloCount = ( | |||
x100, | |||
x10, | |||
x1 | |||
) => { | |||
const getKiloCount: GetKiloCount = (x100, x10, x1) => { | |||
if (x100 < 1) { | |||
return constructTens(x10, x1) | |||
} | |||
@@ -14,11 +10,7 @@ const getKiloCount: GetKiloCount = ( | |||
if (x10 === 0 && x1 === 0) { | |||
return hundredTimes(x100) | |||
} | |||
return [ | |||
hundredTimes(x100), | |||
constructTens(x10, x1), | |||
] | |||
.join(' ') | |||
return [hundredTimes(x100), constructTens(x10, x1)].join(' ') | |||
} | |||
export default getKiloCount |
@@ -34,7 +34,7 @@ test.each` | |||
${17} | ${'thousand octillion'} | |||
${18} | ${'nonillion'} | |||
${19} | ${'thousand nonillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -49,7 +49,7 @@ test.each` | |||
${140} | ${'septuagintillion'} | |||
${160} | ${'octogintillion'} | |||
${180} | ${'nonagintillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -64,7 +64,7 @@ test.each` | |||
${1400} | ${'septingentillion'} | |||
${1600} | ${'octingentillion'} | |||
${1800} | ${'nongentillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -79,7 +79,7 @@ test.each` | |||
${14000} | ${'septenmilliatillion'} | |||
${16000} | ${'octomilliatillion'} | |||
${18000} | ${'novemmilliatillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -94,7 +94,7 @@ test.each` | |||
${140000} | ${'septuaginmilliatillion'} | |||
${160000} | ${'octoginmilliatillion'} | |||
${180000} | ${'nonaginmilliatillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -109,7 +109,7 @@ test.each` | |||
${1400000} | ${'septingenmilliatillion'} | |||
${1600000} | ${'octingenmilliatillion'} | |||
${1800000} | ${'nongenmilliatillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -124,6 +124,6 @@ test.each` | |||
${14000000} | ${'septenmilliamilliatillion'} | |||
${16000000} | ${'octomilliamilliatillion'} | |||
${18000000} | ${'novemmilliamilliatillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) |
@@ -1,8 +1,8 @@ | |||
import { GetKiloName, } from '../../common/NumberSystem' | |||
import { GetKiloName } from '../../NumberSystem' | |||
import NAMES from './names.json' | |||
import getKiloCombiningPrefix from './base/kilo/combiningPrefix' | |||
const getLongKiloName: GetKiloName = thousandPower => { | |||
const getLongKiloName: GetKiloName = (thousandPower) => { | |||
if (thousandPower === 0) { | |||
return '' | |||
} | |||
@@ -11,19 +11,11 @@ const getLongKiloName: GetKiloName = thousandPower => { | |||
} | |||
const kilo = thousandPower | |||
const kiloHundreds = Math.floor(kilo / 2 / 100) | |||
const kiloTens = Math.floor(kilo / 2 / 10 % 10) | |||
const kiloOnes = Math.floor(kilo / 2 % 10) | |||
const baseKiloName = getKiloCombiningPrefix( | |||
kiloHundreds, | |||
kiloTens, | |||
kiloOnes | |||
) + NAMES.kiloEvenSuffix | |||
const kiloTens = Math.floor((kilo / 2 / 10) % 10) | |||
const kiloOnes = Math.floor((kilo / 2) % 10) | |||
const baseKiloName = getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes) + NAMES.kiloEvenSuffix | |||
return ( | |||
thousandPower % 2 === 0 | |||
? baseKiloName | |||
: NAMES.thousand + ' ' + baseKiloName | |||
) | |||
return thousandPower % 2 === 0 ? baseKiloName : NAMES.thousand + ' ' + baseKiloName | |||
} | |||
export default getLongKiloName |
@@ -25,7 +25,7 @@ test.each` | |||
${8} | ${'septillion'} | |||
${9} | ${'octillion'} | |||
${10} | ${'nonillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -40,7 +40,7 @@ test.each` | |||
${71} | ${'septuagintillion'} | |||
${81} | ${'octogintillion'} | |||
${91} | ${'nonagintillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -55,7 +55,7 @@ test.each` | |||
${701} | ${'septingentillion'} | |||
${801} | ${'octingentillion'} | |||
${901} | ${'nongentillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -70,7 +70,7 @@ test.each` | |||
${7001} | ${'septenmilliatillion'} | |||
${8001} | ${'octomilliatillion'} | |||
${9001} | ${'novemmilliatillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -85,7 +85,7 @@ test.each` | |||
${70001} | ${'septuaginmilliatillion'} | |||
${80001} | ${'octoginmilliatillion'} | |||
${90001} | ${'nonaginmilliatillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -100,7 +100,7 @@ test.each` | |||
${700001} | ${'septingenmilliatillion'} | |||
${800001} | ${'octingenmilliatillion'} | |||
${900001} | ${'nongenmilliatillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) | |||
@@ -115,6 +115,6 @@ test.each` | |||
${7000001} | ${'septenmilliamilliatillion'} | |||
${8000001} | ${'octomilliamilliatillion'} | |||
${9000001} | ${'novemmilliamilliatillion'} | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => { | |||
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { | |||
expect(getKiloName(thousandPower)).toBe(name) | |||
}) |
@@ -1,8 +1,8 @@ | |||
import { GetKiloName, } from '../../common/NumberSystem' | |||
import { GetKiloName } from '../../NumberSystem' | |||
import NAMES from './names.json' | |||
import getKiloCombiningPrefix from './base/kilo/combiningPrefix' | |||
const getKiloName: GetKiloName = thousandPower => { | |||
const getKiloName: GetKiloName = (thousandPower) => { | |||
if (thousandPower === 0) { | |||
return '' | |||
} | |||
@@ -11,14 +11,10 @@ const getKiloName: GetKiloName = thousandPower => { | |||
} | |||
const kilo = thousandPower - 1 | |||
const kiloHundreds = Math.floor(kilo / 100) | |||
const kiloTens = Math.floor(kilo / 10 % 10) | |||
const kiloTens = Math.floor((kilo / 10) % 10) | |||
const kiloOnes = Math.floor(kilo % 10) | |||
return getKiloCombiningPrefix( | |||
kiloHundreds, | |||
kiloTens, | |||
kiloOnes | |||
) + NAMES.kiloEvenSuffix | |||
return getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes) + NAMES.kiloEvenSuffix | |||
} | |||
export default getKiloName |
@@ -23,6 +23,6 @@ test.each` | |||
${7} | ${'700'} | ${'pitongdaan'} | |||
${8} | ${'800'} | ${'walongdaan'} | |||
${9} | ${'900'} | ${'siyamnaraan'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(hundredTimes(value)).toBe(name) | |||
}) |
@@ -48,12 +48,7 @@ const hundredTimes: HundredTimes = (x100) => { | |||
break | |||
} | |||
return [ | |||
hundredFactorCombining, | |||
infix, | |||
hundredSuffixCombining, | |||
] | |||
.join('') | |||
return [hundredFactorCombining, infix, hundredSuffixCombining].join('') | |||
} | |||
export default hundredTimes |
@@ -25,7 +25,7 @@ describe('on 0 in hundreds place', () => { | |||
${7} | ${'7'} | ${'septi'} | |||
${8} | ${'8'} | ${'okti'} | |||
${9} | ${'9'} | ${'noni'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(combiningPrefix(0, 0, value)).toBe(name) | |||
}) | |||
}) | |||
@@ -41,7 +41,7 @@ describe('on 0 in hundreds place', () => { | |||
${7} | ${'septuwahinti'} | |||
${8} | ${'oktohinti'} | |||
${9} | ${'nonahinti'} | |||
`('on $tens in tens place', ({ tens, tensName, }) => { | |||
`('on $tens in tens place', ({ tens, tensName }) => { | |||
test.each` | |||
ones | display | |||
${0} | ${tensName} | |||
@@ -54,7 +54,7 @@ describe('on 0 in hundreds place', () => { | |||
${7} | ${'septen' + tensName} | |||
${8} | ${'okto' + tensName} | |||
${9} | ${'nobem' + tensName} | |||
`(`should return "$display" for ${tens}$ones`, ({ ones, display, }) => { | |||
`(`should return "$display" for ${tens}$ones`, ({ ones, display }) => { | |||
expect(combiningPrefix(0, tens, ones)).toBe(display) | |||
}) | |||
}) | |||
@@ -71,7 +71,7 @@ describe.each` | |||
${7} | ${'septinghen'} | |||
${8} | ${'oktinghen'} | |||
${9} | ${'nonghen'} | |||
`('on $hundreds in hundreds place', ({ hundreds, hundredsName, }) => { | |||
`('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => { | |||
describe.each` | |||
tens | tensName | |||
${0} | ${'ti'} | |||
@@ -84,7 +84,7 @@ describe.each` | |||
${7} | ${'septuwahinti'} | |||
${8} | ${'oktohinti'} | |||
${9} | ${'nonahinti'} | |||
`('on $tens in tens place', ({ tens, tensName, }) => { | |||
`('on $tens in tens place', ({ tens, tensName }) => { | |||
test.each` | |||
ones | display | |||
${0} | ${hundredsName + tensName} | |||
@@ -97,7 +97,7 @@ describe.each` | |||
${7} | ${hundredsName + 'septen' + tensName} | |||
${8} | ${hundredsName + 'okto' + tensName} | |||
${9} | ${hundredsName + 'nobem' + tensName} | |||
`(`should return "$display" for ${hundreds}${tens}$ones`, ({ ones, display, }) => { | |||
`(`should return "$display" for ${hundreds}${tens}$ones`, ({ ones, display }) => { | |||
expect(combiningPrefix(hundreds, tens, ones)).toBe(display) | |||
}) | |||
}) | |||
@@ -114,7 +114,7 @@ describe.each` | |||
${7} | ${'septinghen'} | |||
${8} | ${'oktinghen'} | |||
${9} | ${'nonghen'} | |||
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName, }) => { | |||
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName }) => { | |||
describe.each` | |||
tenThousands | tenThousandsName | |||
${0} | ${''} | |||
@@ -127,7 +127,7 @@ describe.each` | |||
${7} | ${'septuwahin'} | |||
${8} | ${'oktohin'} | |||
${9} | ${'nonahin'} | |||
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName, }) => { | |||
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName }) => { | |||
test.each` | |||
thousands | display | name | |||
${0} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milyati'} | |||
@@ -140,17 +140,9 @@ describe.each` | |||
${7000} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milyati'} | |||
${8000} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'okto' + tenThousandsName + 'milyati'} | |||
${9000} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'nobem' + tenThousandsName + 'milyati'} | |||
`(`should return "$name" for $display`, ({ thousands, name, }) => { | |||
const kiloHundreds = ( | |||
hundredThousands * 1000 | |||
+ tenThousands * 100 | |||
+ thousands / 100 | |||
) | |||
expect(combiningPrefix( | |||
kiloHundreds, | |||
0, | |||
0, | |||
)).toBe(name) | |||
`(`should return "$name" for $display`, ({ thousands, name }) => { | |||
const kiloHundreds = hundredThousands * 1000 + tenThousands * 100 + thousands / 100 | |||
expect(combiningPrefix(kiloHundreds, 0, 0)).toBe(name) | |||
}) | |||
}) | |||
}) | |||
@@ -166,7 +158,7 @@ it.each` | |||
${7} | ${'7000000'} | ${'septenmilyamilyati'} | |||
${8} | ${'8000000'} | ${'oktomilyamilyati'} | |||
${9} | ${'9000000'} | ${'nobemmilyamilyati'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(combiningPrefix(value * 10000, 0, 0)).toBe(name) | |||
}) | |||
@@ -181,7 +173,6 @@ it.each` | |||
${7} | ${'7007000'} | ${'septenmilyamilyaseptenmilyati'} | |||
${8} | ${'8008000'} | ${'oktomilyamilyaoktomilyati'} | |||
${9} | ${'9009000'} | ${'nobemmilyamilyanobemmilyati'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(combiningPrefix(value * 10010, 0, 0)).toBe(name) | |||
}) | |||
@@ -4,20 +4,10 @@ import tens from './tens' | |||
import hundreds from './hundreds' | |||
interface CombiningPrefix { | |||
( | |||
kiloHundreds: number, | |||
kiloTens: number, | |||
kiloOnes: number, | |||
kiloPower?: number, | |||
): string, | |||
(kiloHundreds: number, kiloTens: number, kiloOnes: number, kiloPower?: number): string | |||
} | |||
const combiningPrefix: CombiningPrefix = ( | |||
kiloHundredsRaw, | |||
kiloTens, | |||
kiloOnes, | |||
kiloPower = 0, | |||
) => { | |||
const combiningPrefix: CombiningPrefix = (kiloHundredsRaw, kiloTens, kiloOnes, kiloPower = 0) => { | |||
let kiloHundreds = kiloHundredsRaw | |||
let prefix = '' | |||
@@ -25,8 +15,8 @@ const combiningPrefix: CombiningPrefix = ( | |||
if (isMillia) { | |||
prefix += combiningPrefix( | |||
Math.floor(kiloHundredsRaw / 1000), | |||
Math.floor(kiloHundredsRaw / 100 % 10), | |||
Math.floor(kiloHundredsRaw / 10 % 10), | |||
Math.floor((kiloHundredsRaw / 100) % 10), | |||
Math.floor((kiloHundredsRaw / 10) % 10), | |||
kiloPower + 1, | |||
) | |||
kiloHundreds = kiloHundredsRaw % 10 | |||
@@ -38,43 +28,18 @@ const combiningPrefix: CombiningPrefix = ( | |||
} | |||
if ( | |||
( | |||
kiloPower > 0 | |||
&& ( | |||
( | |||
kiloHundreds === 0 | |||
&& kiloTens === 0 | |||
&& kiloOnes > 1 | |||
) | |||
|| ( | |||
( | |||
kiloHundreds > 0 | |||
|| kiloTens > 0 | |||
) | |||
&& kiloOnes > 0 | |||
) | |||
|| ( | |||
kiloHundreds === 0 | |||
&& kiloTens === 0 | |||
&& kiloOnes === 1 | |||
&& prefix.endsWith(NAMES.kiloThousand) | |||
) | |||
) | |||
) | |||
kiloPower > 0 && | |||
((kiloHundreds === 0 && kiloTens === 0 && kiloOnes > 1) || | |||
((kiloHundreds > 0 || kiloTens > 0) && kiloOnes > 0) || | |||
(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 1 && prefix.endsWith(NAMES.kiloThousand))) | |||
) { | |||
// http://www.isthe.com/chongo/tech/math/number/howhigh.html | |||
// Section: Titanic size numbers < 10^3000003 | |||
prefix += ones( | |||
kiloOnes, | |||
false | |||
) | |||
prefix += ones(kiloOnes, false) | |||
} | |||
if (kiloPower === 0 && kiloOnes > 0) { | |||
const special = kiloHundreds === 0 && kiloTens === 0 | |||
prefix += ones( | |||
kiloOnes, | |||
special | |||
) | |||
prefix += ones(kiloOnes, special) | |||
if (special && [5, 6].includes(kiloOnes)) { | |||
prefix += 't' | |||
} | |||
@@ -84,11 +49,7 @@ const combiningPrefix: CombiningPrefix = ( | |||
} | |||
if (kiloPower > 0) { | |||
if (!( | |||
kiloHundreds === 0 | |||
&& kiloTens === 0 | |||
&& kiloOnes === 0 | |||
)) { | |||
if (!(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 0)) { | |||
for (let p = 0; p < kiloPower; p += 1) { | |||
prefix += NAMES.kiloThousand | |||
} | |||
@@ -96,11 +57,7 @@ const combiningPrefix: CombiningPrefix = ( | |||
return prefix | |||
} | |||
if ( | |||
(kiloHundreds === 0 && kiloTens > 1) | |||
|| (kiloHundreds > 0 && kiloTens !== 1) | |||
|| kiloHundredsRaw >= 10 | |||
) { | |||
if ((kiloHundreds === 0 && kiloTens > 1) || (kiloHundreds > 0 && kiloTens !== 1) || kiloHundredsRaw >= 10) { | |||
prefix += 't' | |||
} | |||
return prefix + 'i' | |||
@@ -23,6 +23,6 @@ test.each` | |||
${7} | ${'700'} | ${'septinghen'} | |||
${8} | ${'800'} | ${'oktinghen'} | |||
${9} | ${'900'} | ${'nonghen'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(hundreds(value)).toBe(name) | |||
}) |
@@ -1,7 +1,7 @@ | |||
import NAMES from '../../names.json' | |||
interface Hundreds { | |||
(kiloHundreds: number): string, | |||
(kiloHundreds: number): string | |||
} | |||
const hundreds: Hundreds = (kiloHundreds) => NAMES.kiloHundreds[kiloHundreds] | |||
@@ -25,7 +25,7 @@ describe('on ordinary units', () => { | |||
${7} | ${'7'} | ${'septen'} | |||
${8} | ${'8'} | ${'okto'} | |||
${9} | ${'9'} | ${'nobem'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(ones(value, false)).toBe(name) | |||
}) | |||
}) | |||
@@ -43,7 +43,7 @@ describe('on special units', () => { | |||
${7} | ${'7'} | ${'sept'} | |||
${8} | ${'8'} | ${'okt'} | |||
${9} | ${'9'} | ${'non'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(ones(value, true)).toBe(name) | |||
}) | |||
}) |
@@ -1,13 +1,10 @@ | |||
import NAMES from '../../names.json' | |||
interface Ones { | |||
(kiloOnes: number, special: boolean): string, | |||
(kiloOnes: number, special: boolean): string | |||
} | |||
const ones: Ones = (kiloOnes, special = false) => ( | |||
special | |||
? NAMES.kiloSpecialUnits[kiloOnes] | |||
: NAMES.kiloUnits[kiloOnes] | |||
) | |||
const ones: Ones = (kiloOnes, special = false) => | |||
special ? NAMES.kiloSpecialUnits[kiloOnes] : NAMES.kiloUnits[kiloOnes] | |||
export default ones |
@@ -23,6 +23,6 @@ test.each` | |||
${7} | ${'70'} | ${'septuwahin'} | |||
${8} | ${'80'} | ${'oktohin'} | |||
${9} | ${'90'} | ${'nonahin'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(tens(value)).toBe(name) | |||
}) |
@@ -1,7 +1,7 @@ | |||
import NAMES from '../../names.json' | |||
interface Tens { | |||
(kiloTens: number): string, | |||
(kiloTens: number): string | |||
} | |||
const tens: Tens = (kiloTens) => NAMES.kiloTens[kiloTens] | |||
@@ -24,7 +24,6 @@ test.each` | |||
${7} | ${'7'} | ${'pito'} | |||
${8} | ${'8'} | ${'walo'} | |||
${9} | ${'9'} | ${'siyam'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(ones(value)).toBe(name) | |||
}) | |||
@@ -24,6 +24,6 @@ test.each` | |||
${7} | ${'17'} | ${'labimpito'} | |||
${8} | ${'18'} | ${'labingwalo'} | |||
${9} | ${'19'} | ${'labinsiyam'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(tenPlus(value)).toBe(name) | |||
}) |
@@ -23,6 +23,6 @@ test.each` | |||
${7} | ${'70'} | ${'pitumpu'} | |||
${8} | ${'80'} | ${'walumpu'} | |||
${9} | ${'90'} | ${'siyamnapu'} | |||
`('should return "$name" on $display', ({ value, name, }) => { | |||
`('should return "$name" on $display', ({ value, name }) => { | |||
expect(tenTimes(value)).toBe(name) | |||
}) |
@@ -25,7 +25,7 @@ describe('on 0 in tens place', () => { | |||
${7} | ${'pito'} | |||
${8} | ${'walo'} | |||
${9} | ${'siyam'} | |||
`(`should return "$onesName" for $ones`, ({ ones, onesName, }) => { | |||
`(`should return "$onesName" for $ones`, ({ ones, onesName }) => { | |||
expect(tensFn(0, ones)).toBe(onesName) | |||
}) | |||
}) | |||
@@ -43,38 +43,35 @@ describe('on 1 in tens place', () => { | |||
${7} | ${'labimpito'} | |||
${8} | ${'labingwalo'} | |||
${9} | ${'labinsiyam'} | |||
`(`should return "$tenPlusName" for 1$ones`, ({ ones, tenPlusName, }) => { | |||
`(`should return "$tenPlusName" for 1$ones`, ({ ones, tenPlusName }) => { | |||
expect(tensFn(1, ones)).toBe(tenPlusName) | |||
}) | |||
}) | |||
describe.each` | |||
tens | tensName | |||
${2} | ${'dalawampu'} | |||
${3} | ${'tatlumpu'} | |||
${4} | ${'apatnapu'} | |||
${5} | ${'limampu'} | |||
${6} | ${'animnapu'} | |||
${7} | ${'pitumpu'} | |||
${8} | ${'walumpu'} | |||
${9} | ${'siyamnapu'} | |||
`('on $tens in tens place', ({ tens, tensName, }) => { | |||
tens | tensName | |||
${2} | ${'dalawampu'} | |||
${3} | ${'tatlumpu'} | |||
${4} | ${'apatnapu'} | |||
${5} | ${'limampu'} | |||
${6} | ${'animnapu'} | |||
${7} | ${'pitumpu'} | |||
${8} | ${'walumpu'} | |||
${9} | ${'siyamnapu'} | |||
`('on $tens in tens place', ({ tens, tensName }) => { | |||
test.each` | |||
ones | onesName | |||
${0} | ${''} | |||
${1} | ${'\'t isa'} | |||
${2} | ${'\'t dalawa'} | |||
${3} | ${'\'t tatlo'} | |||
${4} | ${'\'t apat'} | |||
${5} | ${'\'t lima'} | |||
${6} | ${'\'t anim'} | |||
${7} | ${'\'t pito'} | |||
${8} | ${'\'t walo'} | |||
${9} | ${'\'t siyam'} | |||
`(`should return "${tensName}$onesName" for ${tens}$ones`, ({ ones, onesName, }) => { | |||
expect(tensFn(tens, ones)).toBe([ | |||
tensName, | |||
onesName | |||
].join('')) | |||
ones | onesName | |||
${0} | ${''} | |||
${1} | ${"'t isa"} | |||
${2} | ${"'t dalawa"} | |||
${3} | ${"'t tatlo"} | |||
${4} | ${"'t apat"} | |||
${5} | ${"'t lima"} | |||
${6} | ${"'t anim"} | |||
${7} | ${"'t pito"} | |||
${8} | ${"'t walo"} | |||
${9} | ${"'t siyam"} | |||
`(`should return "${tensName}$onesName" for ${tens}$ones`, ({ ones, onesName }) => { | |||
expect(tensFn(tens, ones)).toBe([tensName, onesName].join('')) | |||
}) | |||
}) |
@@ -4,7 +4,7 @@ import tenPlus from '../base/tenPlus' | |||
import getBaseTenTimesName from '../base/tenTimes' | |||
interface Tens { | |||
(x10: number, x1: number): string, | |||
(x10: number, x1: number): string | |||
} | |||
const tens: Tens = (x10, x1) => { | |||
@@ -20,18 +20,7 @@ const tens: Tens = (x10, x1) => { | |||
break | |||
} | |||
return ( | |||
x1 > 0 | |||
? [ | |||
getBaseTenTimesName(x10), | |||
"'", | |||
NAMES.and.slice(1), | |||
' ', | |||
ones(x1), | |||
] | |||
.join('') | |||
: getBaseTenTimesName(x10) | |||
) | |||
return x1 > 0 ? [getBaseTenTimesName(x10), "'", NAMES.and.slice(1), ' ', ones(x1)].join('') : getBaseTenTimesName(x10) | |||
} | |||
export default tens |
@@ -23,7 +23,7 @@ describe.each` | |||
${7} | ${'pitongdaan'} | |||
${8} | ${'walongdaan'} | |||
${9} | ${'siyamnaraan'} | |||
`('on $hundreds in hundreds place', ({ hundreds, hundredsName, }) => { | |||
`('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => { | |||
describe('on 0 in tens place', () => { | |||
test.each` | |||
ones | onesName | |||
@@ -37,13 +37,10 @@ describe.each` | |||
${7} | ${' at pito'} | |||
${8} | ${' at walo'} | |||
${9} | ${' at siyam'} | |||
`(`should return "${hundredsName}$onesName" for ${hundreds}0$ones`, ({ ones, onesName, }) => { | |||
expect(getKiloCount(hundreds, 0, ones)).toBe([ | |||
hundredsName, | |||
onesName | |||
].join('')) | |||
}) | |||
`(`should return "${hundredsName}$onesName" for ${hundreds}0$ones`, ({ ones, onesName }) => { | |||
expect(getKiloCount(hundreds, 0, ones)).toBe([hundredsName, onesName].join('')) | |||
}) | |||
}) | |||
describe('on 1 in tens place', () => { | |||
test.each` | |||
@@ -58,13 +55,10 @@ describe.each` | |||
${7} | ${' labimpito'} | |||
${8} | ${' labingwalo'} | |||
${9} | ${' labinsiyam'} | |||
`(`should return "${hundredsName}$tenPlusName" for ${hundreds}1$ones`, ({ ones, tenPlusName, }) => { | |||
expect(getKiloCount(hundreds, 1, ones)).toBe([ | |||
hundredsName, | |||
tenPlusName | |||
].join('')) | |||
}) | |||
`(`should return "${hundredsName}$tenPlusName" for ${hundreds}1$ones`, ({ ones, tenPlusName }) => { | |||
expect(getKiloCount(hundreds, 1, ones)).toBe([hundredsName, tenPlusName].join('')) | |||
}) | |||
}) | |||
describe.each` | |||
tens | tensName | |||
@@ -76,31 +70,24 @@ describe.each` | |||
${7} | ${' pitumpu'} | |||
${8} | ${' walumpu'} | |||
${9} | ${' siyamnapu'} | |||
`('on $tens in tens place', ({ tens, tensName, }) => { | |||
`('on $tens in tens place', ({ tens, tensName }) => { | |||
it(`should return "${hundredsName} at${tensName}" for ${hundreds}${tens}0`, () => { | |||
expect(getKiloCount(hundreds, tens, 0)).toBe([ | |||
hundredsName, | |||
tensName, | |||
].join(' at')) | |||
expect(getKiloCount(hundreds, tens, 0)).toBe([hundredsName, tensName].join(' at')) | |||
}) | |||
test.each` | |||
ones | onesName | |||
${1} | ${'\'t isa'} | |||
${2} | ${'\'t dalawa'} | |||
${3} | ${'\'t tatlo'} | |||
${4} | ${'\'t apat'} | |||
${5} | ${'\'t lima'} | |||
${6} | ${'\'t anim'} | |||
${7} | ${'\'t pito'} | |||
${8} | ${'\'t walo'} | |||
${9} | ${'\'t siyam'} | |||
`(`should return "${hundredsName}${tensName}$onesName" for ${hundreds}${tens}$ones`, ({ ones, onesName, }) => { | |||
expect(getKiloCount(hundreds, tens, ones)).toBe([ | |||
hundredsName, | |||
tensName, | |||
onesName | |||
].join('')) | |||
${1} | ${"'t isa"} | |||
${2} | ${"'t dalawa"} | |||
${3} | ${"'t tatlo"} | |||
${4} | ${"'t apat"} | |||
${5} | ${"'t lima"} | |||
${6} | ${"'t anim"} | |||
${7} | ${"'t pito"} | |||
${8} | ${"'t walo"} | |||
${9} | ${"'t siyam"} | |||
`(`should return "${hundredsName}${tensName}$onesName" for ${hundreds}${tens}$ones`, ({ ones, onesName }) => { | |||
expect(getKiloCount(hundreds, tens, ones)).toBe([hundredsName, tensName, onesName].join('')) | |||
}) | |||
}) | |||
}) |
@@ -1,13 +1,9 @@ | |||
import NAMES from './names.json' | |||
import { GetKiloCount, } from '../../common/NumberSystem' | |||
import { GetKiloCount } from '../../NumberSystem' | |||
import constructTens from './construct/tens' | |||
import hundredTimes from './base/hundredTimes' | |||
const getKiloCount: GetKiloCount = ( | |||
x100, | |||
x10, | |||
x1 | |||
) => { | |||
const getKiloCount: GetKiloCount = (x100, x10, x1) => { | |||
if (x100 < 1) { | |||
return constructTens(x10, x1) | |||
} | |||
@@ -16,26 +12,12 @@ const getKiloCount: GetKiloCount = ( | |||
if (x1 === 0) { | |||
return hundredTimes(x100) | |||
} | |||
return [ | |||
hundredTimes(x100), | |||
NAMES.and, | |||
constructTens(0, x1), | |||
] | |||
.join(' ') | |||
return [hundredTimes(x100), NAMES.and, constructTens(0, x1)].join(' ') | |||
} | |||
if (x1 === 0) { | |||
return [ | |||
hundredTimes(x100), | |||
NAMES.and, | |||
constructTens(x10, x1), | |||
] | |||
.join(' ') | |||
return [hundredTimes(x100), NAMES.and, constructTens(x10, x1)].join(' ') | |||
} | |||
return [ | |||
hundredTimes(x100), | |||
constructTens(x10, x1), | |||
] | |||
.join(' ') | |||
return [hundredTimes(x100), constructTens(x10, x1)].join(' ') | |||
} | |||
export default getKiloCount |
@@ -0,0 +1,54 @@ | |||
import fs from 'fs' | |||
import Converter from '../src' | |||
import English from '../src/systems/en' | |||
describe.each` | |||
name | system | scale | |||
${'English'} | ${English} | ${'short'} | |||
${'English'} | ${English} | ${'long'} | |||
`('$name ($scale count)', ({ system, scale, }) => { | |||
let converter: Converter | |||
beforeAll(() => { | |||
converter = new Converter(system) | |||
}) | |||
describe('on values', () => { | |||
test.each` | |||
value | name | |||
${1000000} | ${'one million'} | |||
${123456789} | ${'one hundred twenty three million four hundred fifty six thousand seven hundred eighty nine'} | |||
`('should parse $value as $name', ({ value, name, }) => { | |||
expect(converter.convert(value, { scale })).toBe(name) | |||
}) | |||
}) | |||
describe('on streams', () => { | |||
const ENCODING = 'utf-8' | |||
test.each([ | |||
'million.txt' | |||
])('should correctly parse a stream', async (filename) => { | |||
const inputStream = fs.createReadStream( | |||
`./tests/input/${filename}`, | |||
{ | |||
encoding: ENCODING, | |||
highWaterMark: 3, // this is required to parse kilos correctly | |||
} | |||
) | |||
const readStream = converter.readStream({ | |||
scale, | |||
encoding: ENCODING | |||
}) | |||
inputStream | |||
.pipe(readStream) | |||
.pipe(fs.createWriteStream(`./tests/output/${filename}`)) | |||
return new Promise((resolve) => { | |||
readStream.on('end', () => { | |||
resolve('Hello') | |||
}) | |||
}) | |||
}) | |||
}) | |||
}) |
@@ -0,0 +1 @@ | |||
987000321 |
@@ -1155,6 +1155,11 @@ | |||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.27.tgz#a151873af5a5e851b51b3b065c9e63390a9e0eb1" | |||
integrity sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g== | |||
"@types/node@^14.6.0": | |||
version "14.6.0" | |||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.0.tgz#7d4411bf5157339337d7cff864d9ff45f177b499" | |||
integrity sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA== | |||
"@types/parse-json@^4.0.0": | |||
version "4.0.0" | |||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" | |||