diff --git a/package.json b/package.json index 2a4808f..e2c8cac 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,7 @@ { + "name": "@theoryofnekomata/number-name", + "author": "TheoryOfNekomata (https://modal.sh)", + "module": "dist/number-name.esm.js", "version": "0.1.0", "license": "MIT", "main": "dist/index.js", @@ -23,9 +26,6 @@ "pre-commit": "tsdx lint" } }, - "name": "@theoryofnekomata/number-name", - "author": "TheoryOfNekomata (https://modal.sh)", - "module": "dist/number-name.esm.js", "devDependencies": { "@types/node": "^14.6.0", "fast-check": "^2.1.0", diff --git a/src/Converter.ts b/src/Converter.ts index c440af6..5fc1ea2 100644 --- a/src/Converter.ts +++ b/src/Converter.ts @@ -1,33 +1,36 @@ -import NumberSystem from './NumberSystem' import ConverterStream from './ConverterStream' -import { ReadStreamOptions, ConvertOptions } from './common' +import { ReadStreamOptions, ConvertOptions, NumberSystem, Digit } from './common' export default class Converter { constructor(private readonly system: NumberSystem) {} - convert(value: string | number | bigint, options: ConvertOptions) { + public convert = (value: string | number | bigint, options: ConvertOptions): string => { 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) + return this.convert(BigInt(value), options) + case 'bigint': + let current = value as bigint + let thousandPower = 0n + while (current > 0n) { + const hundreds = Number(((current % 1000n) / 100n) % 10n) as Digit + const tens = Number(((current % 100n) / 10n) % 10n) as Digit + const ones = Number(current % 10n) as Digit + + let kiloName: string | undefined + let kiloCount: string if (!(ones === 0 && tens === 0 && hundreds === 0)) { - if (thousandPower > 0) { + if (thousandPower > 0n) { const { scale = 'short' } = options - converted.unshift(this.system.getKiloName[scale!]!(thousandPower)) + kiloName = this.system.getKiloName[scale!]!(thousandPower) } - converted.unshift(this.system.getKiloCount(hundreds, tens, ones)) + kiloCount = this.system.getKiloCount(hundreds, tens, ones) + converted.unshift(this.system.joinKilo(kiloCount, kiloName)) } - thousandPower = thousandPower + 1 - current = Math.floor(current / 1000) + thousandPower = thousandPower + 1n + current = current / 1000n } return converted.join(' ') default: diff --git a/src/ConverterStream.ts b/src/ConverterStream.ts index 6f70e52..88e7327 100644 --- a/src/ConverterStream.ts +++ b/src/ConverterStream.ts @@ -1,16 +1,15 @@ import { Transform } from 'stream' -import NumberSystem from './NumberSystem' -import { ReadStreamOptions } from './common' +import { Digit, NumberSystem, ReadStreamOptions } from './common' export default class ConverterStream extends Transform { - private thousandPower: number = 0 + private thousandPower: bigint = 0n constructor(private readonly system: NumberSystem, private readonly options: ReadStreamOptions) { super() - this.thousandPower = 0 + this.thousandPower = 0n } - _transform(chunk: any, _encoding: BufferEncoding, callback: Function) { + _transform(chunk: Buffer, _encoding: BufferEncoding, callback: Function) { const { scale, encoding } = this.options const [ones = 0, tens = 0, hundreds = 0] = chunk @@ -31,7 +30,7 @@ export default class ConverterStream extends Transform { } this.push( this.system - .getKiloCount(hundreds, tens, ones) + .getKiloCount(hundreds as Digit, tens as Digit, ones as Digit) .split('') .reverse() .join(''), @@ -39,7 +38,7 @@ export default class ConverterStream extends Transform { this.push(' ') } - this.thousandPower = this.thousandPower + 1 + this.thousandPower = this.thousandPower + 1n callback() } } diff --git a/src/NumberSystem.ts b/src/NumberSystem.ts deleted file mode 100644 index 40ced05..0000000 --- a/src/NumberSystem.ts +++ /dev/null @@ -1,10 +0,0 @@ -export type GetKiloCount = (hundreds: number, tens: number, ones: number) => string -export type GetKiloName = (thousandPower: number) => string - -export default interface NumberSystem { - getKiloCount: GetKiloCount - getKiloName: { - short?: GetKiloName - long?: GetKiloName - } -} diff --git a/src/NumberSystemNameTable.ts b/src/NumberSystemNameTable.ts deleted file mode 100644 index 989e93c..0000000 --- a/src/NumberSystemNameTable.ts +++ /dev/null @@ -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 -} diff --git a/src/common.ts b/src/common.ts deleted file mode 100644 index b867649..0000000 --- a/src/common.ts +++ /dev/null @@ -1,11 +0,0 @@ -export type Scale = 'long' | 'short' - -export interface ConvertOptions { - scale?: Scale -} - -export interface StreamOptions { - encoding?: BufferEncoding -} - -export type ReadStreamOptions = ConvertOptions & StreamOptions diff --git a/src/common/index.ts b/src/common/index.ts new file mode 100644 index 0000000..8f84b18 --- /dev/null +++ b/src/common/index.ts @@ -0,0 +1,70 @@ +export type Scale = 'long' | 'short' + +export interface ConvertOptions { + scale?: Scale +} + +export interface StreamOptions { + encoding?: BufferEncoding +} + +type NumberDigit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 + +type StringDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' + +export type Digit = NumberDigit | StringDigit + +export type ReadStreamOptions = ConvertOptions & StreamOptions + +export type GetKiloCount = (hundreds: Digit, tens: Digit, ones: Digit) => string +export type GetKiloName = (thousandPower: bigint) => string +export type JoinKilo = (kiloCount: string, kiloName?: string) => string + +export interface NumberSystem { + getKiloCount: GetKiloCount + getKiloName: { + short?: GetKiloName + long?: GetKiloName + europeanLong?: GetKiloName + } + joinKilo: JoinKilo +} + +interface DigitString { + [0]: string + [1]: string + [2]: string + [3]: string + [4]: string + [5]: string + [6]: string + [7]: string + [8]: string + [9]: string + ['0']: string + ['1']: string + ['2']: string + ['3']: string + ['4']: string + ['5']: string + ['6']: string + ['7']: string + ['8']: string + ['9']: string +} + +export interface NumberSystemNameTable { + units: DigitString + tenPlus: DigitString + tenTimes: DigitString + hundred: string + thousand: string + kiloSpecialUnits: DigitString + kiloUnits: DigitString + kiloTens: DigitString + kiloHundreds: DigitString + kiloThousand: string + kiloEvenSuffix: string + kiloOddSuffix: string + and: string +} diff --git a/src/systems/de/base/hundredTimes.ts b/src/systems/de/base/hundredTimes.ts index 15097ef..db9dee8 100644 --- a/src/systems/de/base/hundredTimes.ts +++ b/src/systems/de/base/hundredTimes.ts @@ -1,7 +1,8 @@ -import NAMES from '../names.json' +import { Digit } from '../../../common' +import NAMES from '../names' interface HundredTimes { - (x100: number): string + (x100: Digit): string } /** @@ -9,6 +10,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) => + Number(x100) === 0 ? NAMES.units[0] : [NAMES.units[x100], NAMES.hundred].join('') export default hundredTimes diff --git a/src/systems/de/base/kilo/combiningPrefix.test.ts b/src/systems/de/base/kilo/combiningPrefix.test.ts index 03482fd..9e180d5 100644 --- a/src/systems/de/base/kilo/combiningPrefix.test.ts +++ b/src/systems/de/base/kilo/combiningPrefix.test.ts @@ -8,8 +8,8 @@ it('should be a callable', () => { expect(typeof combiningPrefix).toBe('function') }) -it('should accept 4 arguments', () => { - expect(combiningPrefix).toHaveLength(4) +it('should accept a minimum of 3 arguments', () => { + expect(combiningPrefix).toHaveLength(3) }) describe('on 0 in hundreds place', () => { @@ -26,7 +26,7 @@ describe('on 0 in hundreds place', () => { ${8} | ${'8'} | ${'octi'} ${9} | ${'9'} | ${'noni'} `('should return "$name" on $display', ({ value, name }) => { - expect(combiningPrefix(0, 0, value)).toBe(name) + expect(combiningPrefix(0n, 0, value)).toBe(name) }) }) @@ -55,22 +55,22 @@ describe('on 0 in hundreds place', () => { ${8} | ${'octo' + tensName} ${9} | ${'novem' + tensName} `(`should return "$display" for ${tens}$ones`, ({ ones, display }) => { - expect(combiningPrefix(0, tens, ones)).toBe(display) + expect(combiningPrefix(0n, tens, ones)).toBe(display) }) }) }) describe.each` hundreds | hundredsName - ${1} | ${'cen'} - ${2} | ${'duocen'} - ${3} | ${'trecen'} - ${4} | ${'quadringen'} - ${5} | ${'quingen'} - ${6} | ${'sescen'} - ${7} | ${'septingen'} - ${8} | ${'octingen'} - ${9} | ${'nongen'} + ${1n} | ${'cen'} + ${2n} | ${'duocen'} + ${3n} | ${'trecen'} + ${4n} | ${'quadringen'} + ${5n} | ${'quingen'} + ${6n} | ${'sescen'} + ${7n} | ${'septingen'} + ${8n} | ${'octingen'} + ${9n} | ${'nongen'} `('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => { describe.each` tens | tensName @@ -105,43 +105,43 @@ describe.each` describe.each` hundredThousands | hundredThousandsName - ${1} | ${'cen'} - ${2} | ${'duocen'} - ${3} | ${'trecen'} - ${4} | ${'quadringen'} - ${5} | ${'quingen'} - ${6} | ${'sescen'} - ${7} | ${'septingen'} - ${8} | ${'octingen'} - ${9} | ${'nongen'} + ${1n} | ${'cen'} + ${2n} | ${'duocen'} + ${3n} | ${'trecen'} + ${4n} | ${'quadringen'} + ${5n} | ${'quingen'} + ${6n} | ${'sescen'} + ${7n} | ${'septingen'} + ${8n} | ${'octingen'} + ${9n} | ${'nongen'} `('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName }) => { describe.each` tenThousands | tenThousandsName - ${0} | ${''} - ${1} | ${'dec'} - ${2} | ${'vigin'} - ${3} | ${'trigin'} - ${4} | ${'quadragin'} - ${5} | ${'quinquagin'} - ${6} | ${'sexagin'} - ${7} | ${'septuagin'} - ${8} | ${'octogin'} - ${9} | ${'nonagin'} + ${0n} | ${''} + ${1n} | ${'dec'} + ${2n} | ${'vigin'} + ${3n} | ${'trigin'} + ${4n} | ${'quadragin'} + ${5n} | ${'quinquagin'} + ${6n} | ${'sexagin'} + ${7n} | ${'septuagin'} + ${8n} | ${'octogin'} + ${9n} | ${'nonagin'} `('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName }) => { test.each` thousands | display | name - ${0} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milliati'} - ${1000} | ${hundredThousands + '' + tenThousands + '1000'} | ${hundredThousandsName + 'un' + tenThousandsName + 'milliati'} - ${2000} | ${hundredThousands + '' + tenThousands + '2000'} | ${hundredThousandsName + 'duo' + tenThousandsName + 'milliati'} - ${3000} | ${hundredThousands + '' + tenThousands + '3000'} | ${hundredThousandsName + 'tre' + tenThousandsName + 'milliati'} - ${4000} | ${hundredThousands + '' + tenThousands + '4000'} | ${hundredThousandsName + 'quattuor' + tenThousandsName + 'milliati'} - ${5000} | ${hundredThousands + '' + tenThousands + '5000'} | ${hundredThousandsName + 'quin' + tenThousandsName + 'milliati'} - ${6000} | ${hundredThousands + '' + tenThousands + '6000'} | ${hundredThousandsName + 'sex' + tenThousandsName + 'milliati'} - ${7000} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milliati'} - ${8000} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'octo' + tenThousandsName + 'milliati'} - ${9000} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'novem' + tenThousandsName + 'milliati'} + ${0n} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milliati'} + ${1000n} | ${hundredThousands + '' + tenThousands + '1000'} | ${hundredThousandsName + 'un' + tenThousandsName + 'milliati'} + ${2000n} | ${hundredThousands + '' + tenThousands + '2000'} | ${hundredThousandsName + 'duo' + tenThousandsName + 'milliati'} + ${3000n} | ${hundredThousands + '' + tenThousands + '3000'} | ${hundredThousandsName + 'tre' + tenThousandsName + 'milliati'} + ${4000n} | ${hundredThousands + '' + tenThousands + '4000'} | ${hundredThousandsName + 'quattuor' + tenThousandsName + 'milliati'} + ${5000n} | ${hundredThousands + '' + tenThousands + '5000'} | ${hundredThousandsName + 'quin' + tenThousandsName + 'milliati'} + ${6000n} | ${hundredThousands + '' + tenThousands + '6000'} | ${hundredThousandsName + 'sex' + tenThousandsName + 'milliati'} + ${7000n} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milliati'} + ${8000n} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'octo' + tenThousandsName + 'milliati'} + ${9000n} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'novem' + tenThousandsName + 'milliati'} `(`should return "$name" for $display`, ({ thousands, name }) => { - const kiloHundreds = hundredThousands * 1000 + tenThousands * 100 + thousands / 100 + const kiloHundreds = hundredThousands * 1000n + tenThousands * 100n + thousands / 100n expect(combiningPrefix(kiloHundreds, 0, 0)).toBe(name) }) }) @@ -149,30 +149,30 @@ describe.each` test.each` value | display | name - ${1} | ${'1000000'} | ${'milliamilliati'} - ${2} | ${'2000000'} | ${'duomilliamilliati'} - ${3} | ${'3000000'} | ${'tremilliamilliati'} - ${4} | ${'4000000'} | ${'quattuormilliamilliati'} - ${5} | ${'5000000'} | ${'quinmilliamilliati'} - ${6} | ${'6000000'} | ${'sexmilliamilliati'} - ${7} | ${'7000000'} | ${'septenmilliamilliati'} - ${8} | ${'8000000'} | ${'octomilliamilliati'} - ${9} | ${'9000000'} | ${'novemmilliamilliati'} + ${1n} | ${'1000000'} | ${'milliamilliati'} + ${2n} | ${'2000000'} | ${'duomilliamilliati'} + ${3n} | ${'3000000'} | ${'tremilliamilliati'} + ${4n} | ${'4000000'} | ${'quattuormilliamilliati'} + ${5n} | ${'5000000'} | ${'quinmilliamilliati'} + ${6n} | ${'6000000'} | ${'sexmilliamilliati'} + ${7n} | ${'7000000'} | ${'septenmilliamilliati'} + ${8n} | ${'8000000'} | ${'octomilliamilliati'} + ${9n} | ${'9000000'} | ${'novemmilliamilliati'} `('should return "$name" on $display', ({ value, name }) => { - expect(combiningPrefix(value * 10000, 0, 0)).toBe(name) + expect(combiningPrefix(value * 10000n, 0, 0)).toBe(name) }) test.each` value | display | name - ${1} | ${'1001000'} | ${'milliamilliaunmilliati'} - ${2} | ${'2002000'} | ${'duomilliamilliaduomilliati'} - ${3} | ${'3003000'} | ${'tremilliamilliatremilliati'} - ${4} | ${'4004000'} | ${'quattuormilliamilliaquattuormilliati'} - ${5} | ${'5005000'} | ${'quinmilliamilliaquinmilliati'} - ${6} | ${'6006000'} | ${'sexmilliamilliasexmilliati'} - ${7} | ${'7007000'} | ${'septenmilliamilliaseptenmilliati'} - ${8} | ${'8008000'} | ${'octomilliamilliaoctomilliati'} - ${9} | ${'9009000'} | ${'novemmilliamillianovemmilliati'} + ${1n} | ${'1001000'} | ${'milliamilliaunmilliati'} + ${2n} | ${'2002000'} | ${'duomilliamilliaduomilliati'} + ${3n} | ${'3003000'} | ${'tremilliamilliatremilliati'} + ${4n} | ${'4004000'} | ${'quattuormilliamilliaquattuormilliati'} + ${5n} | ${'5005000'} | ${'quinmilliamilliaquinmilliati'} + ${6n} | ${'6006000'} | ${'sexmilliamilliasexmilliati'} + ${7n} | ${'7007000'} | ${'septenmilliamilliaseptenmilliati'} + ${8n} | ${'8008000'} | ${'octomilliamilliaoctomilliati'} + ${9n} | ${'9009000'} | ${'novemmilliamillianovemmilliati'} `('should return "$name" on $display', ({ value, name }) => { - expect(combiningPrefix(value * 10010, 0, 0)).toBe(name) + expect(combiningPrefix(value * 10010n, 0, 0)).toBe(name) }) diff --git a/src/systems/de/base/kilo/combiningPrefix.ts b/src/systems/de/base/kilo/combiningPrefix.ts index 7901b61..f724c81 100644 --- a/src/systems/de/base/kilo/combiningPrefix.ts +++ b/src/systems/de/base/kilo/combiningPrefix.ts @@ -1,63 +1,74 @@ -import NAMES from '../../names.json' +import { Digit } from '../../../../common' +import NAMES from '../../names' import ones from './ones' import tens from './tens' import hundreds from './hundreds' interface CombiningPrefix { - (kiloHundreds: number, kiloTens: number, kiloOnes: number, kiloPower?: number): string + (kiloHundreds: bigint, kiloTens: Digit, kiloOnes: Digit, kiloPower?: bigint): string } -const combiningPrefix: CombiningPrefix = (kiloHundredsRaw, kiloTens, kiloOnes, kiloPower = 0) => { - let kiloHundreds = kiloHundredsRaw +const combiningPrefix: CombiningPrefix = (kiloHundreds, kiloTens, kiloOnes, kiloPower = 0n) => { + let currentKiloHundreds = kiloHundreds let prefix = '' - const isMillia = kiloHundredsRaw >= 10 + const isMillia = kiloHundreds >= 10n if (isMillia) { prefix += combiningPrefix( - Math.floor(kiloHundredsRaw / 1000), - Math.floor((kiloHundredsRaw / 100) % 10), - Math.floor((kiloHundredsRaw / 10) % 10), - kiloPower + 1, + kiloHundreds / 1000n, + (Number(kiloHundreds / 100n) % 10) as Digit, + (Number(kiloHundreds / 10n) % 10) as Digit, + kiloPower + 1n, ) - kiloHundreds = kiloHundredsRaw % 10 + currentKiloHundreds = kiloHundreds % 10n } - const hasHundreds = kiloHundreds > 0 + const hasHundreds = currentKiloHundreds > 0n if (hasHundreds) { - prefix += hundreds(kiloHundreds) + prefix += hundreds(Number(currentKiloHundreds % 10n) as Digit) } + const kiloTensNumber = Number(kiloTens) + const kiloOnesNumber = Number(kiloOnes) + 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))) + ((currentKiloHundreds === 0n && kiloTensNumber === 0 && kiloOnesNumber > 1) || + ((currentKiloHundreds > 0n || kiloTensNumber > 0) && kiloOnesNumber > 0) || + (currentKiloHundreds === 0n && + kiloTensNumber === 0 && + kiloOnesNumber === 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) } - if (kiloPower === 0 && kiloOnes > 0) { - const special = kiloHundreds === 0 && kiloTens === 0 + if (kiloPower === 0n && kiloOnesNumber) { + const special = currentKiloHundreds === 0n && kiloTensNumber === 0 prefix += ones(kiloOnes, special) - if (special && [5, 6].includes(kiloOnes)) { + if (special && [5, 6].includes(Number(kiloOnes))) { prefix += 't' } } - if (kiloTens > 0) { + if (kiloTensNumber > 0) { prefix += tens(kiloTens) } - if (kiloPower > 0) { - if (!(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 0)) { - for (let p = 0; p < kiloPower; p += 1) { + if (kiloPower > 0n) { + if (!(currentKiloHundreds === 0n && kiloTensNumber === 0 && kiloOnesNumber === 0)) { + for (let p = 0n; p < kiloPower; p += 1n) { prefix += NAMES.kiloThousand } } return prefix } - if ((kiloHundreds === 0 && kiloTens > 1) || (kiloHundreds > 0 && kiloTens !== 1) || kiloHundredsRaw >= 10) { + if ( + (currentKiloHundreds === 0n && kiloTensNumber > 1) || + (currentKiloHundreds > 0n && kiloTensNumber !== 1) || + kiloHundreds >= 10 + ) { prefix += 't' } return prefix + 'i' diff --git a/src/systems/de/base/kilo/hundreds.ts b/src/systems/de/base/kilo/hundreds.ts index 9d24831..b6ba02e 100644 --- a/src/systems/de/base/kilo/hundreds.ts +++ b/src/systems/de/base/kilo/hundreds.ts @@ -1,7 +1,8 @@ -import NAMES from '../../names.json' +import { Digit } from '../../../../common' +import NAMES from '../../names' interface Hundreds { - (kiloHundreds: number): string + (kiloHundreds: Digit): string } const hundreds: Hundreds = (kiloHundreds) => NAMES.kiloHundreds[kiloHundreds] diff --git a/src/systems/de/base/kilo/ones.test.ts b/src/systems/de/base/kilo/ones.test.ts index 31ec3af..c580f4f 100644 --- a/src/systems/de/base/kilo/ones.test.ts +++ b/src/systems/de/base/kilo/ones.test.ts @@ -8,8 +8,8 @@ it('should be a callable', () => { expect(typeof ones).toBe('function') }) -it('should accept 2 arguments', () => { - expect(ones).toHaveLength(2) +it('should accept a minimum of 1 argument', () => { + expect(ones).toHaveLength(1) }) describe('on ordinary units', () => { diff --git a/src/systems/de/base/kilo/ones.ts b/src/systems/de/base/kilo/ones.ts index 0b11d0d..64dbffe 100644 --- a/src/systems/de/base/kilo/ones.ts +++ b/src/systems/de/base/kilo/ones.ts @@ -1,7 +1,8 @@ -import NAMES from '../../names.json' +import { Digit } from '../../../../common' +import NAMES from '../../names' interface Ones { - (kiloOnes: number, special: boolean): string + (kiloOnes: Digit, special: boolean): string } const ones: Ones = (kiloOnes, special = false) => diff --git a/src/systems/de/base/kilo/tens.ts b/src/systems/de/base/kilo/tens.ts index 54f9975..7cecc98 100644 --- a/src/systems/de/base/kilo/tens.ts +++ b/src/systems/de/base/kilo/tens.ts @@ -1,7 +1,8 @@ -import NAMES from '../../names.json' +import { Digit } from '../../../../common' +import NAMES from '../../names' interface Tens { - (kiloTens: number): string + (kiloTens: Digit): string } const tens: Tens = (kiloTens) => NAMES.kiloTens[kiloTens] diff --git a/src/systems/de/base/ones.ts b/src/systems/de/base/ones.ts index f63ea33..4c71085 100644 --- a/src/systems/de/base/ones.ts +++ b/src/systems/de/base/ones.ts @@ -1,7 +1,8 @@ -import NAMES from '../names.json' +import { Digit } from '../../../common' +import NAMES from '../names' interface Ones { - (x1: number): string + (x1: Digit): string } /** diff --git a/src/systems/de/base/tenPlus.ts b/src/systems/de/base/tenPlus.ts index ef92973..9236a9c 100644 --- a/src/systems/de/base/tenPlus.ts +++ b/src/systems/de/base/tenPlus.ts @@ -1,7 +1,8 @@ -import NAMES from '../names.json' +import { Digit } from '../../../common' +import NAMES from '../names' interface TenPlus { - (ones: number): string + (ones: Digit): string } /** diff --git a/src/systems/de/base/tenTimes.ts b/src/systems/de/base/tenTimes.ts index 7366877..9a616cc 100644 --- a/src/systems/de/base/tenTimes.ts +++ b/src/systems/de/base/tenTimes.ts @@ -1,7 +1,8 @@ -import NAMES from '../names.json' +import { Digit } from '../../../common' +import NAMES from '../names' interface TenTimes { - (x10: number): string + (x10: Digit): string } /** diff --git a/src/systems/de/construct/tens.ts b/src/systems/de/construct/tens.ts index 124bf93..99afd4c 100644 --- a/src/systems/de/construct/tens.ts +++ b/src/systems/de/construct/tens.ts @@ -1,10 +1,11 @@ -import NAMES from '../names.json' +import { Digit } from '../../../common' +import NAMES from '../names' import ones from '../base/ones' import tenPlus from '../base/tenPlus' import getBaseTenTimesName from '../base/tenTimes' interface Tens { - (x10: number, x1: number): string + (x10: Digit, x1: Digit): string } const tens: Tens = (x10, x1) => { diff --git a/src/systems/de/getEuropeanLongKiloName.test.ts b/src/systems/de/getEuropeanLongKiloName.test.ts new file mode 100644 index 0000000..7608ee5 --- /dev/null +++ b/src/systems/de/getEuropeanLongKiloName.test.ts @@ -0,0 +1,129 @@ +import getEuropeanLongKiloName from './getEuropeanLongKiloName' + +it('should exist', () => { + expect(getEuropeanLongKiloName).toBeDefined() +}) + +it('should be a callable', () => { + expect(typeof getEuropeanLongKiloName).toBe('function') +}) + +it('should accept 1 argument', () => { + expect(getEuropeanLongKiloName).toHaveLength(1) +}) + +test.each` + thousandPower | name + ${0n} | ${''} + ${1n} | ${'tausend'} + ${2n} | ${'million'} + ${3n} | ${'milliard'} + ${4n} | ${'billion'} + ${5n} | ${'billiard'} + ${6n} | ${'trillion'} + ${7n} | ${'trilliard'} + ${8n} | ${'quadrillion'} + ${9n} | ${'quadrilliard'} + ${10n} | ${'quintillion'} + ${11n} | ${'quintilliard'} + ${12n} | ${'sextillion'} + ${13n} | ${'sextilliard'} + ${14n} | ${'septillion'} + ${15n} | ${'septilliard'} + ${16n} | ${'octillion'} + ${17n} | ${'octilliard'} + ${18n} | ${'nonillion'} + ${19n} | ${'nonilliard'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getEuropeanLongKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${20n} | ${'decillion'} + ${40n} | ${'vigintillion'} + ${60n} | ${'trigintillion'} + ${80n} | ${'quadragintillion'} + ${100n} | ${'quinquagintillion'} + ${120n} | ${'sexagintillion'} + ${140n} | ${'septuagintillion'} + ${160n} | ${'octogintillion'} + ${180n} | ${'nonagintillion'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getEuropeanLongKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${200n} | ${'centillion'} + ${400n} | ${'duocentillion'} + ${600n} | ${'trecentillion'} + ${800n} | ${'quadringentillion'} + ${1000n} | ${'quingentillion'} + ${1200n} | ${'sescentillion'} + ${1400n} | ${'septingentillion'} + ${1600n} | ${'octingentillion'} + ${1800n} | ${'nongentillion'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getEuropeanLongKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${2000n} | ${'milliatillion'} + ${4000n} | ${'duomilliatillion'} + ${6000n} | ${'tremilliatillion'} + ${8000n} | ${'quattuormilliatillion'} + ${10000n} | ${'quinmilliatillion'} + ${12000n} | ${'sexmilliatillion'} + ${14000n} | ${'septenmilliatillion'} + ${16000n} | ${'octomilliatillion'} + ${18000n} | ${'novemmilliatillion'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getEuropeanLongKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${20000n} | ${'decmilliatillion'} + ${40000n} | ${'viginmilliatillion'} + ${60000n} | ${'triginmilliatillion'} + ${80000n} | ${'quadraginmilliatillion'} + ${100000n} | ${'quinquaginmilliatillion'} + ${120000n} | ${'sexaginmilliatillion'} + ${140000n} | ${'septuaginmilliatillion'} + ${160000n} | ${'octoginmilliatillion'} + ${180000n} | ${'nonaginmilliatillion'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getEuropeanLongKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${200000n} | ${'cenmilliatillion'} + ${400000n} | ${'duocenmilliatillion'} + ${600000n} | ${'trecenmilliatillion'} + ${800000n} | ${'quadringenmilliatillion'} + ${1000000n} | ${'quingenmilliatillion'} + ${1200000n} | ${'sescenmilliatillion'} + ${1400000n} | ${'septingenmilliatillion'} + ${1600000n} | ${'octingenmilliatillion'} + ${1800000n} | ${'nongenmilliatillion'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getEuropeanLongKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${2000000n} | ${'milliamilliatillion'} + ${4000000n} | ${'duomilliamilliatillion'} + ${6000000n} | ${'tremilliamilliatillion'} + ${8000000n} | ${'quattuormilliamilliatillion'} + ${10000000n} | ${'quinmilliamilliatillion'} + ${12000000n} | ${'sexmilliamilliatillion'} + ${14000000n} | ${'septenmilliamilliatillion'} + ${16000000n} | ${'octomilliamilliatillion'} + ${18000000n} | ${'novemmilliamilliatillion'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getEuropeanLongKiloName(thousandPower)).toBe(name) +}) diff --git a/src/systems/de/getEuropeanLongKiloName.ts b/src/systems/de/getEuropeanLongKiloName.ts new file mode 100644 index 0000000..2d665b7 --- /dev/null +++ b/src/systems/de/getEuropeanLongKiloName.ts @@ -0,0 +1,23 @@ +import { Digit, GetKiloName } from '../../common' +import NAMES from './names' +import getKiloCombiningPrefix from './base/kilo/combiningPrefix' + +const getEuropeanLongKiloName: GetKiloName = (thousandPower) => { + if (thousandPower === 0n) { + return '' + } + if (thousandPower === 1n) { + return NAMES.thousand + } + const kilo = thousandPower + const kiloHundreds = kilo / 2n / 100n + const kiloTens = (Number(kilo / 2n / 10n) % 10) as Digit + const kiloOnes = (Number(kilo / 2n) % 10) as Digit + const kiloCombiningPrefix = getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes) + + return thousandPower % 2n === 0n + ? kiloCombiningPrefix + NAMES.kiloEvenSuffix + : kiloCombiningPrefix + NAMES.kiloOddSuffix +} + +export default getEuropeanLongKiloName diff --git a/src/systems/de/getKiloCount.ts b/src/systems/de/getKiloCount.ts new file mode 100644 index 0000000..d35212a --- /dev/null +++ b/src/systems/de/getKiloCount.ts @@ -0,0 +1,18 @@ +import { GetKiloCount, Digit } from '../../common' +import constructTens from './construct/tens' +import hundredTimes from './base/hundredTimes' + +const getKiloCount: GetKiloCount = (x100Raw, x10, x1) => { + const x100 = Number(BigInt(x100Raw) % 10n) as Digit + if (x100 < 1) { + return constructTens(x10, x1) + } + + if (x10 === 0 && x1 === 0) { + return hundredTimes(x100) + } + + return [hundredTimes(x100), constructTens(x10, x1)].join('') +} + +export default getKiloCount diff --git a/src/systems/de/getLongKiloName.test.ts b/src/systems/de/getLongKiloName.test.ts deleted file mode 100644 index 7c4f621..0000000 --- a/src/systems/de/getLongKiloName.test.ts +++ /dev/null @@ -1,129 +0,0 @@ -import getKiloName from './getLongKiloName' - -it('should exist', () => { - expect(getKiloName).toBeDefined() -}) - -it('should be a callable', () => { - expect(typeof getKiloName).toBe('function') -}) - -it('should accept 1 argument', () => { - expect(getKiloName).toHaveLength(1) -}) - -test.each` - thousandPower | name - ${0} | ${''} - ${1} | ${'Tausend'} - ${2} | ${'Million'} - ${3} | ${'Milliard'} - ${4} | ${'Billion'} - ${5} | ${'Billiard'} - ${6} | ${'Trillion'} - ${7} | ${'Trilliard'} - ${8} | ${'Quadrillion'} - ${9} | ${'Quadrilliard'} - ${10} | ${'Quintillion'} - ${11} | ${'Quintilliard'} - ${12} | ${'Sextillion'} - ${13} | ${'Sextilliard'} - ${14} | ${'Septillion'} - ${15} | ${'Septilliard'} - ${16} | ${'Octillion'} - ${17} | ${'Octilliard'} - ${18} | ${'Nonillion'} - ${19} | ${'Nonilliard'} -`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) -}) - -test.each` - thousandPower | name - ${20} | ${'Decillion'} - ${40} | ${'Vigintillion'} - ${60} | ${'Trigintillion'} - ${80} | ${'Quadragintillion'} - ${100} | ${'Quinquagintillion'} - ${120} | ${'Sexagintillion'} - ${140} | ${'Septuagintillion'} - ${160} | ${'Octogintillion'} - ${180} | ${'Nonagintillion'} -`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) -}) - -test.each` - thousandPower | name - ${200} | ${'Centillion'} - ${400} | ${'Duocentillion'} - ${600} | ${'Trecentillion'} - ${800} | ${'Quadringentillion'} - ${1000} | ${'Quingentillion'} - ${1200} | ${'Sescentillion'} - ${1400} | ${'Septingentillion'} - ${1600} | ${'Octingentillion'} - ${1800} | ${'Nongentillion'} -`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) -}) - -test.each` - thousandPower | name - ${2000} | ${'Milliatillion'} - ${4000} | ${'Duomilliatillion'} - ${6000} | ${'Tremilliatillion'} - ${8000} | ${'Quattuormilliatillion'} - ${10000} | ${'Quinmilliatillion'} - ${12000} | ${'Sexmilliatillion'} - ${14000} | ${'Septenmilliatillion'} - ${16000} | ${'Octomilliatillion'} - ${18000} | ${'Novemmilliatillion'} -`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) -}) - -test.each` - thousandPower | name - ${20000} | ${'Decmilliatillion'} - ${40000} | ${'Viginmilliatillion'} - ${60000} | ${'Triginmilliatillion'} - ${80000} | ${'Quadraginmilliatillion'} - ${100000} | ${'Quinquaginmilliatillion'} - ${120000} | ${'Sexaginmilliatillion'} - ${140000} | ${'Septuaginmilliatillion'} - ${160000} | ${'Octoginmilliatillion'} - ${180000} | ${'Nonaginmilliatillion'} -`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) -}) - -test.each` - thousandPower | name - ${200000} | ${'Cenmilliatillion'} - ${400000} | ${'Duocenmilliatillion'} - ${600000} | ${'Trecenmilliatillion'} - ${800000} | ${'Quadringenmilliatillion'} - ${1000000} | ${'Quingenmilliatillion'} - ${1200000} | ${'Sescenmilliatillion'} - ${1400000} | ${'Septingenmilliatillion'} - ${1600000} | ${'Octingenmilliatillion'} - ${1800000} | ${'Nongenmilliatillion'} -`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) -}) - -test.each` - thousandPower | name - ${2000000} | ${'Milliamilliatillion'} - ${4000000} | ${'Duomilliamilliatillion'} - ${6000000} | ${'Tremilliamilliatillion'} - ${8000000} | ${'Quattuormilliamilliatillion'} - ${10000000} | ${'Quinmilliamilliatillion'} - ${12000000} | ${'Sexmilliamilliatillion'} - ${14000000} | ${'Septenmilliamilliatillion'} - ${16000000} | ${'Octomilliamilliatillion'} - ${18000000} | ${'Novemmilliamilliatillion'} -`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) -}) diff --git a/src/systems/de/getLongKiloName.ts b/src/systems/de/getLongKiloName.ts deleted file mode 100644 index a7c5db5..0000000 --- a/src/systems/de/getLongKiloName.ts +++ /dev/null @@ -1,25 +0,0 @@ -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 getLongKiloName: GetKiloName = (thousandPower) => { - if (thousandPower === 0) { - return '' - } - if (thousandPower === 1) { - return capitalizeFirstLetter(NAMES.thousand) - } - 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) - - return capitalizeFirstLetter( - thousandPower % 2 === 0 ? kiloCombiningPrefix + NAMES.kiloEvenSuffix : kiloCombiningPrefix + NAMES.kiloOddSuffix, - ) -} - -export default getLongKiloName diff --git a/src/systems/de/index.ts b/src/systems/de/index.ts new file mode 100644 index 0000000..53a2c4b --- /dev/null +++ b/src/systems/de/index.ts @@ -0,0 +1,14 @@ +import { NumberSystem } from '../../common' +import getKiloCount from './getKiloCount' +import getEuropeanLongKiloName from './getEuropeanLongKiloName' +import joinKilo from './joinKilo' + +const numberSystem: NumberSystem = { + getKiloCount, + getKiloName: { + europeanLong: getEuropeanLongKiloName, + }, + joinKilo, +} + +export default numberSystem diff --git a/src/systems/de/joinKilo.ts b/src/systems/de/joinKilo.ts new file mode 100644 index 0000000..f7d5d74 --- /dev/null +++ b/src/systems/de/joinKilo.ts @@ -0,0 +1,13 @@ +import { JoinKilo } from '../../common' + +const joinKilo: JoinKilo = (kiloCount, kiloName) => + kiloName + ? [ + kiloCount, + ' ', + kiloName.slice(0, 1).toUpperCase(), // capitalize kilo name + kiloName.slice(1), + ].join('') + : kiloCount + +export default joinKilo diff --git a/src/systems/de/names.json b/src/systems/de/names.json deleted file mode 100644 index d3a4502..0000000 --- a/src/systems/de/names.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "units": [ - "zero", - "ein", - "zwei", - "drei", - "vier", - "fünf", - "sechs", - "sieben", - "acht", - "neun" - ], - "tenPlus": [ - "zehn", - "elf", - "zwölf", - "dreizehn", - "vierzehn", - "fünfzehn", - "sechzehn", - "siebzehn", - "achtzehn", - "neunzehn" - ], - "tenTimes": [ - "zero", - "zehn", - "zwanzig", - "dreißig", - "vierzig", - "fünfzig", - "sechzig", - "siebzig", - "achtzig", - "neunzig" - ], - "hundred": "hundert", - "thousand": "tausend", - "kiloSpecialUnits": [ - "", - "m", - "b", - "tr", - "quadr", - "quin", - "sex", - "sept", - "oct", - "non" - ], - "kiloUnits": [ - "", - "un", - "duo", - "tre", - "quattuor", - "quin", - "sex", - "septen", - "octo", - "novem" - ], - "kiloTens": [ - "", - "dec", - "vigin", - "trigin", - "quadragin", - "quinquagin", - "sexagin", - "septuagin", - "octogin", - "nonagin" - ], - "kiloHundreds": [ - "", - "cen", - "duocen", - "trecen", - "quadringen", - "quingen", - "sescen", - "septingen", - "octingen", - "nongen" - ], - "kiloThousand": "millia", - "kiloEvenSuffix": "llion", - "kiloOddSuffix": "lliard", - "and": "und" -} diff --git a/src/systems/de/names.ts b/src/systems/de/names.ts new file mode 100644 index 0000000..8bca4b1 --- /dev/null +++ b/src/systems/de/names.ts @@ -0,0 +1,19 @@ +import { NumberSystemNameTable } from '../../common' + +const names: NumberSystemNameTable = { + units: ['zero', 'ein', 'zwei', 'drei', 'vier', 'fünf', 'sechs', 'sieben', 'acht', 'neun'], + tenPlus: ['zehn', 'elf', 'zwölf', 'dreizehn', 'vierzehn', 'fünfzehn', 'sechzehn', 'siebzehn', 'achtzehn', 'neunzehn'], + tenTimes: ['zero', 'zehn', 'zwanzig', 'dreißig', 'vierzig', 'fünfzig', 'sechzig', 'siebzig', 'achtzig', 'neunzig'], + hundred: 'hundert', + thousand: 'tausend', + kiloSpecialUnits: ['', 'm', 'b', 'tr', 'quadr', 'quin', 'sex', 'sept', 'oct', 'non'], + kiloUnits: ['', 'un', 'duo', 'tre', 'quattuor', 'quin', 'sex', 'septen', 'octo', 'novem'], + kiloTens: ['', 'dec', 'vigin', 'trigin', 'quadragin', 'quinquagin', 'sexagin', 'septuagin', 'octogin', 'nonagin'], + kiloHundreds: ['', 'cen', 'duocen', 'trecen', 'quadringen', 'quingen', 'sescen', 'septingen', 'octingen', 'nongen'], + kiloThousand: 'millia', + kiloEvenSuffix: 'llion', + kiloOddSuffix: 'lliard', + and: 'und', +} + +export default names diff --git a/src/systems/en.ts b/src/systems/en.ts deleted file mode 100644 index 975bd76..0000000 --- a/src/systems/en.ts +++ /dev/null @@ -1,14 +0,0 @@ -import NumberSystem from '../NumberSystem' -import getKiloCount from './en/getKiloCount' -import getLongKiloName from './en/getLongKiloName' -import getShortKiloName from './en/getShortKiloName' - -const en: NumberSystem = { - getKiloCount, - getKiloName: { - short: getShortKiloName, - long: getLongKiloName, - }, -} - -export default en diff --git a/src/systems/en/base/hundredTimes.ts b/src/systems/en/base/hundredTimes.ts index f3820a9..90ac931 100644 --- a/src/systems/en/base/hundredTimes.ts +++ b/src/systems/en/base/hundredTimes.ts @@ -1,7 +1,8 @@ -import NAMES from '../names.json' +import { Digit } from '../../../common' +import NAMES from '../names' interface HundredTimes { - (x100: number): string + (x100: Digit): string } /** diff --git a/src/systems/en/base/kilo/combiningPrefix.test.ts b/src/systems/en/base/kilo/combiningPrefix.test.ts index 03482fd..9e180d5 100644 --- a/src/systems/en/base/kilo/combiningPrefix.test.ts +++ b/src/systems/en/base/kilo/combiningPrefix.test.ts @@ -8,8 +8,8 @@ it('should be a callable', () => { expect(typeof combiningPrefix).toBe('function') }) -it('should accept 4 arguments', () => { - expect(combiningPrefix).toHaveLength(4) +it('should accept a minimum of 3 arguments', () => { + expect(combiningPrefix).toHaveLength(3) }) describe('on 0 in hundreds place', () => { @@ -26,7 +26,7 @@ describe('on 0 in hundreds place', () => { ${8} | ${'8'} | ${'octi'} ${9} | ${'9'} | ${'noni'} `('should return "$name" on $display', ({ value, name }) => { - expect(combiningPrefix(0, 0, value)).toBe(name) + expect(combiningPrefix(0n, 0, value)).toBe(name) }) }) @@ -55,22 +55,22 @@ describe('on 0 in hundreds place', () => { ${8} | ${'octo' + tensName} ${9} | ${'novem' + tensName} `(`should return "$display" for ${tens}$ones`, ({ ones, display }) => { - expect(combiningPrefix(0, tens, ones)).toBe(display) + expect(combiningPrefix(0n, tens, ones)).toBe(display) }) }) }) describe.each` hundreds | hundredsName - ${1} | ${'cen'} - ${2} | ${'duocen'} - ${3} | ${'trecen'} - ${4} | ${'quadringen'} - ${5} | ${'quingen'} - ${6} | ${'sescen'} - ${7} | ${'septingen'} - ${8} | ${'octingen'} - ${9} | ${'nongen'} + ${1n} | ${'cen'} + ${2n} | ${'duocen'} + ${3n} | ${'trecen'} + ${4n} | ${'quadringen'} + ${5n} | ${'quingen'} + ${6n} | ${'sescen'} + ${7n} | ${'septingen'} + ${8n} | ${'octingen'} + ${9n} | ${'nongen'} `('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => { describe.each` tens | tensName @@ -105,43 +105,43 @@ describe.each` describe.each` hundredThousands | hundredThousandsName - ${1} | ${'cen'} - ${2} | ${'duocen'} - ${3} | ${'trecen'} - ${4} | ${'quadringen'} - ${5} | ${'quingen'} - ${6} | ${'sescen'} - ${7} | ${'septingen'} - ${8} | ${'octingen'} - ${9} | ${'nongen'} + ${1n} | ${'cen'} + ${2n} | ${'duocen'} + ${3n} | ${'trecen'} + ${4n} | ${'quadringen'} + ${5n} | ${'quingen'} + ${6n} | ${'sescen'} + ${7n} | ${'septingen'} + ${8n} | ${'octingen'} + ${9n} | ${'nongen'} `('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName }) => { describe.each` tenThousands | tenThousandsName - ${0} | ${''} - ${1} | ${'dec'} - ${2} | ${'vigin'} - ${3} | ${'trigin'} - ${4} | ${'quadragin'} - ${5} | ${'quinquagin'} - ${6} | ${'sexagin'} - ${7} | ${'septuagin'} - ${8} | ${'octogin'} - ${9} | ${'nonagin'} + ${0n} | ${''} + ${1n} | ${'dec'} + ${2n} | ${'vigin'} + ${3n} | ${'trigin'} + ${4n} | ${'quadragin'} + ${5n} | ${'quinquagin'} + ${6n} | ${'sexagin'} + ${7n} | ${'septuagin'} + ${8n} | ${'octogin'} + ${9n} | ${'nonagin'} `('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName }) => { test.each` thousands | display | name - ${0} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milliati'} - ${1000} | ${hundredThousands + '' + tenThousands + '1000'} | ${hundredThousandsName + 'un' + tenThousandsName + 'milliati'} - ${2000} | ${hundredThousands + '' + tenThousands + '2000'} | ${hundredThousandsName + 'duo' + tenThousandsName + 'milliati'} - ${3000} | ${hundredThousands + '' + tenThousands + '3000'} | ${hundredThousandsName + 'tre' + tenThousandsName + 'milliati'} - ${4000} | ${hundredThousands + '' + tenThousands + '4000'} | ${hundredThousandsName + 'quattuor' + tenThousandsName + 'milliati'} - ${5000} | ${hundredThousands + '' + tenThousands + '5000'} | ${hundredThousandsName + 'quin' + tenThousandsName + 'milliati'} - ${6000} | ${hundredThousands + '' + tenThousands + '6000'} | ${hundredThousandsName + 'sex' + tenThousandsName + 'milliati'} - ${7000} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milliati'} - ${8000} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'octo' + tenThousandsName + 'milliati'} - ${9000} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'novem' + tenThousandsName + 'milliati'} + ${0n} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milliati'} + ${1000n} | ${hundredThousands + '' + tenThousands + '1000'} | ${hundredThousandsName + 'un' + tenThousandsName + 'milliati'} + ${2000n} | ${hundredThousands + '' + tenThousands + '2000'} | ${hundredThousandsName + 'duo' + tenThousandsName + 'milliati'} + ${3000n} | ${hundredThousands + '' + tenThousands + '3000'} | ${hundredThousandsName + 'tre' + tenThousandsName + 'milliati'} + ${4000n} | ${hundredThousands + '' + tenThousands + '4000'} | ${hundredThousandsName + 'quattuor' + tenThousandsName + 'milliati'} + ${5000n} | ${hundredThousands + '' + tenThousands + '5000'} | ${hundredThousandsName + 'quin' + tenThousandsName + 'milliati'} + ${6000n} | ${hundredThousands + '' + tenThousands + '6000'} | ${hundredThousandsName + 'sex' + tenThousandsName + 'milliati'} + ${7000n} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milliati'} + ${8000n} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'octo' + tenThousandsName + 'milliati'} + ${9000n} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'novem' + tenThousandsName + 'milliati'} `(`should return "$name" for $display`, ({ thousands, name }) => { - const kiloHundreds = hundredThousands * 1000 + tenThousands * 100 + thousands / 100 + const kiloHundreds = hundredThousands * 1000n + tenThousands * 100n + thousands / 100n expect(combiningPrefix(kiloHundreds, 0, 0)).toBe(name) }) }) @@ -149,30 +149,30 @@ describe.each` test.each` value | display | name - ${1} | ${'1000000'} | ${'milliamilliati'} - ${2} | ${'2000000'} | ${'duomilliamilliati'} - ${3} | ${'3000000'} | ${'tremilliamilliati'} - ${4} | ${'4000000'} | ${'quattuormilliamilliati'} - ${5} | ${'5000000'} | ${'quinmilliamilliati'} - ${6} | ${'6000000'} | ${'sexmilliamilliati'} - ${7} | ${'7000000'} | ${'septenmilliamilliati'} - ${8} | ${'8000000'} | ${'octomilliamilliati'} - ${9} | ${'9000000'} | ${'novemmilliamilliati'} + ${1n} | ${'1000000'} | ${'milliamilliati'} + ${2n} | ${'2000000'} | ${'duomilliamilliati'} + ${3n} | ${'3000000'} | ${'tremilliamilliati'} + ${4n} | ${'4000000'} | ${'quattuormilliamilliati'} + ${5n} | ${'5000000'} | ${'quinmilliamilliati'} + ${6n} | ${'6000000'} | ${'sexmilliamilliati'} + ${7n} | ${'7000000'} | ${'septenmilliamilliati'} + ${8n} | ${'8000000'} | ${'octomilliamilliati'} + ${9n} | ${'9000000'} | ${'novemmilliamilliati'} `('should return "$name" on $display', ({ value, name }) => { - expect(combiningPrefix(value * 10000, 0, 0)).toBe(name) + expect(combiningPrefix(value * 10000n, 0, 0)).toBe(name) }) test.each` value | display | name - ${1} | ${'1001000'} | ${'milliamilliaunmilliati'} - ${2} | ${'2002000'} | ${'duomilliamilliaduomilliati'} - ${3} | ${'3003000'} | ${'tremilliamilliatremilliati'} - ${4} | ${'4004000'} | ${'quattuormilliamilliaquattuormilliati'} - ${5} | ${'5005000'} | ${'quinmilliamilliaquinmilliati'} - ${6} | ${'6006000'} | ${'sexmilliamilliasexmilliati'} - ${7} | ${'7007000'} | ${'septenmilliamilliaseptenmilliati'} - ${8} | ${'8008000'} | ${'octomilliamilliaoctomilliati'} - ${9} | ${'9009000'} | ${'novemmilliamillianovemmilliati'} + ${1n} | ${'1001000'} | ${'milliamilliaunmilliati'} + ${2n} | ${'2002000'} | ${'duomilliamilliaduomilliati'} + ${3n} | ${'3003000'} | ${'tremilliamilliatremilliati'} + ${4n} | ${'4004000'} | ${'quattuormilliamilliaquattuormilliati'} + ${5n} | ${'5005000'} | ${'quinmilliamilliaquinmilliati'} + ${6n} | ${'6006000'} | ${'sexmilliamilliasexmilliati'} + ${7n} | ${'7007000'} | ${'septenmilliamilliaseptenmilliati'} + ${8n} | ${'8008000'} | ${'octomilliamilliaoctomilliati'} + ${9n} | ${'9009000'} | ${'novemmilliamillianovemmilliati'} `('should return "$name" on $display', ({ value, name }) => { - expect(combiningPrefix(value * 10010, 0, 0)).toBe(name) + expect(combiningPrefix(value * 10010n, 0, 0)).toBe(name) }) diff --git a/src/systems/en/base/kilo/combiningPrefix.ts b/src/systems/en/base/kilo/combiningPrefix.ts index 7901b61..f724c81 100644 --- a/src/systems/en/base/kilo/combiningPrefix.ts +++ b/src/systems/en/base/kilo/combiningPrefix.ts @@ -1,63 +1,74 @@ -import NAMES from '../../names.json' +import { Digit } from '../../../../common' +import NAMES from '../../names' import ones from './ones' import tens from './tens' import hundreds from './hundreds' interface CombiningPrefix { - (kiloHundreds: number, kiloTens: number, kiloOnes: number, kiloPower?: number): string + (kiloHundreds: bigint, kiloTens: Digit, kiloOnes: Digit, kiloPower?: bigint): string } -const combiningPrefix: CombiningPrefix = (kiloHundredsRaw, kiloTens, kiloOnes, kiloPower = 0) => { - let kiloHundreds = kiloHundredsRaw +const combiningPrefix: CombiningPrefix = (kiloHundreds, kiloTens, kiloOnes, kiloPower = 0n) => { + let currentKiloHundreds = kiloHundreds let prefix = '' - const isMillia = kiloHundredsRaw >= 10 + const isMillia = kiloHundreds >= 10n if (isMillia) { prefix += combiningPrefix( - Math.floor(kiloHundredsRaw / 1000), - Math.floor((kiloHundredsRaw / 100) % 10), - Math.floor((kiloHundredsRaw / 10) % 10), - kiloPower + 1, + kiloHundreds / 1000n, + (Number(kiloHundreds / 100n) % 10) as Digit, + (Number(kiloHundreds / 10n) % 10) as Digit, + kiloPower + 1n, ) - kiloHundreds = kiloHundredsRaw % 10 + currentKiloHundreds = kiloHundreds % 10n } - const hasHundreds = kiloHundreds > 0 + const hasHundreds = currentKiloHundreds > 0n if (hasHundreds) { - prefix += hundreds(kiloHundreds) + prefix += hundreds(Number(currentKiloHundreds % 10n) as Digit) } + const kiloTensNumber = Number(kiloTens) + const kiloOnesNumber = Number(kiloOnes) + 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))) + ((currentKiloHundreds === 0n && kiloTensNumber === 0 && kiloOnesNumber > 1) || + ((currentKiloHundreds > 0n || kiloTensNumber > 0) && kiloOnesNumber > 0) || + (currentKiloHundreds === 0n && + kiloTensNumber === 0 && + kiloOnesNumber === 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) } - if (kiloPower === 0 && kiloOnes > 0) { - const special = kiloHundreds === 0 && kiloTens === 0 + if (kiloPower === 0n && kiloOnesNumber) { + const special = currentKiloHundreds === 0n && kiloTensNumber === 0 prefix += ones(kiloOnes, special) - if (special && [5, 6].includes(kiloOnes)) { + if (special && [5, 6].includes(Number(kiloOnes))) { prefix += 't' } } - if (kiloTens > 0) { + if (kiloTensNumber > 0) { prefix += tens(kiloTens) } - if (kiloPower > 0) { - if (!(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 0)) { - for (let p = 0; p < kiloPower; p += 1) { + if (kiloPower > 0n) { + if (!(currentKiloHundreds === 0n && kiloTensNumber === 0 && kiloOnesNumber === 0)) { + for (let p = 0n; p < kiloPower; p += 1n) { prefix += NAMES.kiloThousand } } return prefix } - if ((kiloHundreds === 0 && kiloTens > 1) || (kiloHundreds > 0 && kiloTens !== 1) || kiloHundredsRaw >= 10) { + if ( + (currentKiloHundreds === 0n && kiloTensNumber > 1) || + (currentKiloHundreds > 0n && kiloTensNumber !== 1) || + kiloHundreds >= 10 + ) { prefix += 't' } return prefix + 'i' diff --git a/src/systems/en/base/kilo/hundreds.ts b/src/systems/en/base/kilo/hundreds.ts index 9d24831..b6ba02e 100644 --- a/src/systems/en/base/kilo/hundreds.ts +++ b/src/systems/en/base/kilo/hundreds.ts @@ -1,7 +1,8 @@ -import NAMES from '../../names.json' +import { Digit } from '../../../../common' +import NAMES from '../../names' interface Hundreds { - (kiloHundreds: number): string + (kiloHundreds: Digit): string } const hundreds: Hundreds = (kiloHundreds) => NAMES.kiloHundreds[kiloHundreds] diff --git a/src/systems/en/base/kilo/ones.test.ts b/src/systems/en/base/kilo/ones.test.ts index 31ec3af..c580f4f 100644 --- a/src/systems/en/base/kilo/ones.test.ts +++ b/src/systems/en/base/kilo/ones.test.ts @@ -8,8 +8,8 @@ it('should be a callable', () => { expect(typeof ones).toBe('function') }) -it('should accept 2 arguments', () => { - expect(ones).toHaveLength(2) +it('should accept a minimum of 1 argument', () => { + expect(ones).toHaveLength(1) }) describe('on ordinary units', () => { diff --git a/src/systems/en/base/kilo/ones.ts b/src/systems/en/base/kilo/ones.ts index 0b11d0d..64dbffe 100644 --- a/src/systems/en/base/kilo/ones.ts +++ b/src/systems/en/base/kilo/ones.ts @@ -1,7 +1,8 @@ -import NAMES from '../../names.json' +import { Digit } from '../../../../common' +import NAMES from '../../names' interface Ones { - (kiloOnes: number, special: boolean): string + (kiloOnes: Digit, special: boolean): string } const ones: Ones = (kiloOnes, special = false) => diff --git a/src/systems/en/base/kilo/tens.ts b/src/systems/en/base/kilo/tens.ts index 54f9975..7cecc98 100644 --- a/src/systems/en/base/kilo/tens.ts +++ b/src/systems/en/base/kilo/tens.ts @@ -1,7 +1,8 @@ -import NAMES from '../../names.json' +import { Digit } from '../../../../common' +import NAMES from '../../names' interface Tens { - (kiloTens: number): string + (kiloTens: Digit): string } const tens: Tens = (kiloTens) => NAMES.kiloTens[kiloTens] diff --git a/src/systems/en/base/ones.ts b/src/systems/en/base/ones.ts index f63ea33..4c71085 100644 --- a/src/systems/en/base/ones.ts +++ b/src/systems/en/base/ones.ts @@ -1,7 +1,8 @@ -import NAMES from '../names.json' +import { Digit } from '../../../common' +import NAMES from '../names' interface Ones { - (x1: number): string + (x1: Digit): string } /** diff --git a/src/systems/en/base/tenPlus.ts b/src/systems/en/base/tenPlus.ts index ef92973..9236a9c 100644 --- a/src/systems/en/base/tenPlus.ts +++ b/src/systems/en/base/tenPlus.ts @@ -1,7 +1,8 @@ -import NAMES from '../names.json' +import { Digit } from '../../../common' +import NAMES from '../names' interface TenPlus { - (ones: number): string + (ones: Digit): string } /** diff --git a/src/systems/en/base/tenTimes.ts b/src/systems/en/base/tenTimes.ts index 7366877..9a616cc 100644 --- a/src/systems/en/base/tenTimes.ts +++ b/src/systems/en/base/tenTimes.ts @@ -1,7 +1,8 @@ -import NAMES from '../names.json' +import { Digit } from '../../../common' +import NAMES from '../names' interface TenTimes { - (x10: number): string + (x10: Digit): string } /** diff --git a/src/systems/en/construct/tens.ts b/src/systems/en/construct/tens.ts index 62ddba4..b9128c4 100644 --- a/src/systems/en/construct/tens.ts +++ b/src/systems/en/construct/tens.ts @@ -1,9 +1,10 @@ +import { Digit } from '../../../common' import ones from '../base/ones' import tenPlus from '../base/tenPlus' import getBaseTenTimesName from '../base/tenTimes' interface Tens { - (x10: number, x1: number): string + (x10: Digit, x1: Digit): string } const tens: Tens = (x10, x1) => { diff --git a/src/systems/en/getEuropeanLongKiloName.test.ts b/src/systems/en/getEuropeanLongKiloName.test.ts new file mode 100644 index 0000000..dd5a33f --- /dev/null +++ b/src/systems/en/getEuropeanLongKiloName.test.ts @@ -0,0 +1,129 @@ +import getEuropeanLongKiloName from './getEuropeanLongKiloName' + +it('should exist', () => { + expect(getEuropeanLongKiloName).toBeDefined() +}) + +it('should be a callable', () => { + expect(typeof getEuropeanLongKiloName).toBe('function') +}) + +it('should accept 1 argument', () => { + expect(getEuropeanLongKiloName).toHaveLength(1) +}) + +test.each` + thousandPower | name + ${0n} | ${''} + ${1n} | ${'thousand'} + ${2n} | ${'million'} + ${3n} | ${'milliard'} + ${4n} | ${'billion'} + ${5n} | ${'billiard'} + ${6n} | ${'trillion'} + ${7n} | ${'trilliard'} + ${8n} | ${'quadrillion'} + ${9n} | ${'quadrilliard'} + ${10n} | ${'quintillion'} + ${11n} | ${'quintilliard'} + ${12n} | ${'sextillion'} + ${13n} | ${'sextilliard'} + ${14n} | ${'septillion'} + ${15n} | ${'septilliard'} + ${16n} | ${'octillion'} + ${17n} | ${'octilliard'} + ${18n} | ${'nonillion'} + ${19n} | ${'nonilliard'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getEuropeanLongKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${20n} | ${'decillion'} + ${40n} | ${'vigintillion'} + ${60n} | ${'trigintillion'} + ${80n} | ${'quadragintillion'} + ${100n} | ${'quinquagintillion'} + ${120n} | ${'sexagintillion'} + ${140n} | ${'septuagintillion'} + ${160n} | ${'octogintillion'} + ${180n} | ${'nonagintillion'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getEuropeanLongKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${200n} | ${'centillion'} + ${400n} | ${'duocentillion'} + ${600n} | ${'trecentillion'} + ${800n} | ${'quadringentillion'} + ${1000n} | ${'quingentillion'} + ${1200n} | ${'sescentillion'} + ${1400n} | ${'septingentillion'} + ${1600n} | ${'octingentillion'} + ${1800n} | ${'nongentillion'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getEuropeanLongKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${2000n} | ${'milliatillion'} + ${4000n} | ${'duomilliatillion'} + ${6000n} | ${'tremilliatillion'} + ${8000n} | ${'quattuormilliatillion'} + ${10000n} | ${'quinmilliatillion'} + ${12000n} | ${'sexmilliatillion'} + ${14000n} | ${'septenmilliatillion'} + ${16000n} | ${'octomilliatillion'} + ${18000n} | ${'novemmilliatillion'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getEuropeanLongKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${20000n} | ${'decmilliatillion'} + ${40000n} | ${'viginmilliatillion'} + ${60000n} | ${'triginmilliatillion'} + ${80000n} | ${'quadraginmilliatillion'} + ${100000n} | ${'quinquaginmilliatillion'} + ${120000n} | ${'sexaginmilliatillion'} + ${140000n} | ${'septuaginmilliatillion'} + ${160000n} | ${'octoginmilliatillion'} + ${180000n} | ${'nonaginmilliatillion'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getEuropeanLongKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${200000n} | ${'cenmilliatillion'} + ${400000n} | ${'duocenmilliatillion'} + ${600000n} | ${'trecenmilliatillion'} + ${800000n} | ${'quadringenmilliatillion'} + ${1000000n} | ${'quingenmilliatillion'} + ${1200000n} | ${'sescenmilliatillion'} + ${1400000n} | ${'septingenmilliatillion'} + ${1600000n} | ${'octingenmilliatillion'} + ${1800000n} | ${'nongenmilliatillion'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getEuropeanLongKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${2000000n} | ${'milliamilliatillion'} + ${4000000n} | ${'duomilliamilliatillion'} + ${6000000n} | ${'tremilliamilliatillion'} + ${8000000n} | ${'quattuormilliamilliatillion'} + ${10000000n} | ${'quinmilliamilliatillion'} + ${12000000n} | ${'sexmilliamilliatillion'} + ${14000000n} | ${'septenmilliamilliatillion'} + ${16000000n} | ${'octomilliamilliatillion'} + ${18000000n} | ${'novemmilliamilliatillion'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getEuropeanLongKiloName(thousandPower)).toBe(name) +}) diff --git a/src/systems/en/getEuropeanLongKiloName.ts b/src/systems/en/getEuropeanLongKiloName.ts new file mode 100644 index 0000000..2d665b7 --- /dev/null +++ b/src/systems/en/getEuropeanLongKiloName.ts @@ -0,0 +1,23 @@ +import { Digit, GetKiloName } from '../../common' +import NAMES from './names' +import getKiloCombiningPrefix from './base/kilo/combiningPrefix' + +const getEuropeanLongKiloName: GetKiloName = (thousandPower) => { + if (thousandPower === 0n) { + return '' + } + if (thousandPower === 1n) { + return NAMES.thousand + } + const kilo = thousandPower + const kiloHundreds = kilo / 2n / 100n + const kiloTens = (Number(kilo / 2n / 10n) % 10) as Digit + const kiloOnes = (Number(kilo / 2n) % 10) as Digit + const kiloCombiningPrefix = getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes) + + return thousandPower % 2n === 0n + ? kiloCombiningPrefix + NAMES.kiloEvenSuffix + : kiloCombiningPrefix + NAMES.kiloOddSuffix +} + +export default getEuropeanLongKiloName diff --git a/src/systems/en/getKiloCount.ts b/src/systems/en/getKiloCount.ts index 3f6fd3e..300663b 100644 --- a/src/systems/en/getKiloCount.ts +++ b/src/systems/en/getKiloCount.ts @@ -1,8 +1,9 @@ -import { GetKiloCount } from '../../NumberSystem' +import { GetKiloCount, Digit } from '../../common' import constructTens from './construct/tens' import hundredTimes from './base/hundredTimes' -const getKiloCount: GetKiloCount = (x100, x10, x1) => { +const getKiloCount: GetKiloCount = (x100Raw, x10, x1) => { + const x100 = Number(BigInt(x100Raw) % 10n) as Digit if (x100 < 1) { return constructTens(x10, x1) } @@ -10,6 +11,7 @@ const getKiloCount: GetKiloCount = (x100, x10, x1) => { if (x10 === 0 && x1 === 0) { return hundredTimes(x100) } + return [hundredTimes(x100), constructTens(x10, x1)].join(' ') } diff --git a/src/systems/en/getLongKiloName.test.ts b/src/systems/en/getLongKiloName.test.ts index e37c4f6..09b5e0f 100644 --- a/src/systems/en/getLongKiloName.test.ts +++ b/src/systems/en/getLongKiloName.test.ts @@ -1,129 +1,129 @@ -import getKiloName from './getLongKiloName' +import getLongKiloName from './getLongKiloName' it('should exist', () => { - expect(getKiloName).toBeDefined() + expect(getLongKiloName).toBeDefined() }) it('should be a callable', () => { - expect(typeof getKiloName).toBe('function') + expect(typeof getLongKiloName).toBe('function') }) it('should accept 1 argument', () => { - expect(getKiloName).toHaveLength(1) + expect(getLongKiloName).toHaveLength(1) }) test.each` thousandPower | name - ${0} | ${''} - ${1} | ${'thousand'} - ${2} | ${'million'} - ${3} | ${'thousand million'} - ${4} | ${'billion'} - ${5} | ${'thousand billion'} - ${6} | ${'trillion'} - ${7} | ${'thousand trillion'} - ${8} | ${'quadrillion'} - ${9} | ${'thousand quadrillion'} - ${10} | ${'quintillion'} - ${11} | ${'thousand quintillion'} - ${12} | ${'sextillion'} - ${13} | ${'thousand sextillion'} - ${14} | ${'septillion'} - ${15} | ${'thousand septillion'} - ${16} | ${'octillion'} - ${17} | ${'thousand octillion'} - ${18} | ${'nonillion'} - ${19} | ${'thousand nonillion'} + ${0n} | ${''} + ${1n} | ${'thousand'} + ${2n} | ${'million'} + ${3n} | ${'thousand million'} + ${4n} | ${'billion'} + ${5n} | ${'thousand billion'} + ${6n} | ${'trillion'} + ${7n} | ${'thousand trillion'} + ${8n} | ${'quadrillion'} + ${9n} | ${'thousand quadrillion'} + ${10n} | ${'quintillion'} + ${11n} | ${'thousand quintillion'} + ${12n} | ${'sextillion'} + ${13n} | ${'thousand sextillion'} + ${14n} | ${'septillion'} + ${15n} | ${'thousand septillion'} + ${16n} | ${'octillion'} + ${17n} | ${'thousand octillion'} + ${18n} | ${'nonillion'} + ${19n} | ${'thousand nonillion'} `('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) + expect(getLongKiloName(thousandPower)).toBe(name) }) test.each` thousandPower | name - ${20} | ${'decillion'} - ${40} | ${'vigintillion'} - ${60} | ${'trigintillion'} - ${80} | ${'quadragintillion'} - ${100} | ${'quinquagintillion'} - ${120} | ${'sexagintillion'} - ${140} | ${'septuagintillion'} - ${160} | ${'octogintillion'} - ${180} | ${'nonagintillion'} + ${20n} | ${'decillion'} + ${40n} | ${'vigintillion'} + ${60n} | ${'trigintillion'} + ${80n} | ${'quadragintillion'} + ${100n} | ${'quinquagintillion'} + ${120n} | ${'sexagintillion'} + ${140n} | ${'septuagintillion'} + ${160n} | ${'octogintillion'} + ${180n} | ${'nonagintillion'} `('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) + expect(getLongKiloName(thousandPower)).toBe(name) }) test.each` thousandPower | name - ${200} | ${'centillion'} - ${400} | ${'duocentillion'} - ${600} | ${'trecentillion'} - ${800} | ${'quadringentillion'} - ${1000} | ${'quingentillion'} - ${1200} | ${'sescentillion'} - ${1400} | ${'septingentillion'} - ${1600} | ${'octingentillion'} - ${1800} | ${'nongentillion'} + ${200n} | ${'centillion'} + ${400n} | ${'duocentillion'} + ${600n} | ${'trecentillion'} + ${800n} | ${'quadringentillion'} + ${1000n} | ${'quingentillion'} + ${1200n} | ${'sescentillion'} + ${1400n} | ${'septingentillion'} + ${1600n} | ${'octingentillion'} + ${1800n} | ${'nongentillion'} `('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) + expect(getLongKiloName(thousandPower)).toBe(name) }) test.each` thousandPower | name - ${2000} | ${'milliatillion'} - ${4000} | ${'duomilliatillion'} - ${6000} | ${'tremilliatillion'} - ${8000} | ${'quattuormilliatillion'} - ${10000} | ${'quinmilliatillion'} - ${12000} | ${'sexmilliatillion'} - ${14000} | ${'septenmilliatillion'} - ${16000} | ${'octomilliatillion'} - ${18000} | ${'novemmilliatillion'} + ${2000n} | ${'milliatillion'} + ${4000n} | ${'duomilliatillion'} + ${6000n} | ${'tremilliatillion'} + ${8000n} | ${'quattuormilliatillion'} + ${10000n} | ${'quinmilliatillion'} + ${12000n} | ${'sexmilliatillion'} + ${14000n} | ${'septenmilliatillion'} + ${16000n} | ${'octomilliatillion'} + ${18000n} | ${'novemmilliatillion'} `('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) + expect(getLongKiloName(thousandPower)).toBe(name) }) test.each` thousandPower | name - ${20000} | ${'decmilliatillion'} - ${40000} | ${'viginmilliatillion'} - ${60000} | ${'triginmilliatillion'} - ${80000} | ${'quadraginmilliatillion'} - ${100000} | ${'quinquaginmilliatillion'} - ${120000} | ${'sexaginmilliatillion'} - ${140000} | ${'septuaginmilliatillion'} - ${160000} | ${'octoginmilliatillion'} - ${180000} | ${'nonaginmilliatillion'} + ${20000n} | ${'decmilliatillion'} + ${40000n} | ${'viginmilliatillion'} + ${60000n} | ${'triginmilliatillion'} + ${80000n} | ${'quadraginmilliatillion'} + ${100000n} | ${'quinquaginmilliatillion'} + ${120000n} | ${'sexaginmilliatillion'} + ${140000n} | ${'septuaginmilliatillion'} + ${160000n} | ${'octoginmilliatillion'} + ${180000n} | ${'nonaginmilliatillion'} `('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) + expect(getLongKiloName(thousandPower)).toBe(name) }) test.each` thousandPower | name - ${200000} | ${'cenmilliatillion'} - ${400000} | ${'duocenmilliatillion'} - ${600000} | ${'trecenmilliatillion'} - ${800000} | ${'quadringenmilliatillion'} - ${1000000} | ${'quingenmilliatillion'} - ${1200000} | ${'sescenmilliatillion'} - ${1400000} | ${'septingenmilliatillion'} - ${1600000} | ${'octingenmilliatillion'} - ${1800000} | ${'nongenmilliatillion'} + ${200000n} | ${'cenmilliatillion'} + ${400000n} | ${'duocenmilliatillion'} + ${600000n} | ${'trecenmilliatillion'} + ${800000n} | ${'quadringenmilliatillion'} + ${1000000n} | ${'quingenmilliatillion'} + ${1200000n} | ${'sescenmilliatillion'} + ${1400000n} | ${'septingenmilliatillion'} + ${1600000n} | ${'octingenmilliatillion'} + ${1800000n} | ${'nongenmilliatillion'} `('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) + expect(getLongKiloName(thousandPower)).toBe(name) }) test.each` thousandPower | name - ${2000000} | ${'milliamilliatillion'} - ${4000000} | ${'duomilliamilliatillion'} - ${6000000} | ${'tremilliamilliatillion'} - ${8000000} | ${'quattuormilliamilliatillion'} - ${10000000} | ${'quinmilliamilliatillion'} - ${12000000} | ${'sexmilliamilliatillion'} - ${14000000} | ${'septenmilliamilliatillion'} - ${16000000} | ${'octomilliamilliatillion'} - ${18000000} | ${'novemmilliamilliatillion'} + ${2000000n} | ${'milliamilliatillion'} + ${4000000n} | ${'duomilliamilliatillion'} + ${6000000n} | ${'tremilliamilliatillion'} + ${8000000n} | ${'quattuormilliamilliatillion'} + ${10000000n} | ${'quinmilliamilliatillion'} + ${12000000n} | ${'sexmilliamilliatillion'} + ${14000000n} | ${'septenmilliamilliatillion'} + ${16000000n} | ${'octomilliamilliatillion'} + ${18000000n} | ${'novemmilliamilliatillion'} `('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) + expect(getLongKiloName(thousandPower)).toBe(name) }) diff --git a/src/systems/en/getLongKiloName.ts b/src/systems/en/getLongKiloName.ts index b558937..516b6cf 100644 --- a/src/systems/en/getLongKiloName.ts +++ b/src/systems/en/getLongKiloName.ts @@ -1,21 +1,21 @@ -import { GetKiloName } from '../../NumberSystem' -import NAMES from './names.json' +import { Digit, GetKiloName } from '../../common' +import NAMES from './names' import getKiloCombiningPrefix from './base/kilo/combiningPrefix' const getLongKiloName: GetKiloName = (thousandPower) => { - if (thousandPower === 0) { + if (thousandPower === 0n) { return '' } - if (thousandPower === 1) { + if (thousandPower === 1n) { return NAMES.thousand } 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 kiloHundreds = kilo / 2n / 100n + const kiloTens = (Number(kilo / 2n / 10n) % 10) as Digit + const kiloOnes = (Number(kilo / 2n) % 10) as Digit const baseKiloName = getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes) + NAMES.kiloEvenSuffix - return thousandPower % 2 === 0 ? baseKiloName : NAMES.thousand + ' ' + baseKiloName + return thousandPower % 2n === 0n ? baseKiloName : NAMES.thousand + ' ' + baseKiloName } export default getLongKiloName diff --git a/src/systems/en/getShortKiloName.test.ts b/src/systems/en/getShortKiloName.test.ts index 75524e7..1bd9c8f 100644 --- a/src/systems/en/getShortKiloName.test.ts +++ b/src/systems/en/getShortKiloName.test.ts @@ -1,120 +1,120 @@ -import getKiloName from './getShortKiloName' +import getShortKiloName from './getShortKiloName' it('should exist', () => { - expect(getKiloName).toBeDefined() + expect(getShortKiloName).toBeDefined() }) it('should be a callable', () => { - expect(typeof getKiloName).toBe('function') + expect(typeof getShortKiloName).toBe('function') }) it('should accept 1 argument', () => { - expect(getKiloName).toHaveLength(1) + expect(getShortKiloName).toHaveLength(1) }) test.each` thousandPower | name - ${0} | ${''} - ${1} | ${'thousand'} - ${2} | ${'million'} - ${3} | ${'billion'} - ${4} | ${'trillion'} - ${5} | ${'quadrillion'} - ${6} | ${'quintillion'} - ${7} | ${'sextillion'} - ${8} | ${'septillion'} - ${9} | ${'octillion'} - ${10} | ${'nonillion'} + ${0n} | ${''} + ${1n} | ${'thousand'} + ${2n} | ${'million'} + ${3n} | ${'billion'} + ${4n} | ${'trillion'} + ${5n} | ${'quadrillion'} + ${6n} | ${'quintillion'} + ${7n} | ${'sextillion'} + ${8n} | ${'septillion'} + ${9n} | ${'octillion'} + ${10n} | ${'nonillion'} `('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) + expect(getShortKiloName(thousandPower)).toBe(name) }) test.each` thousandPower | name - ${11} | ${'decillion'} - ${21} | ${'vigintillion'} - ${31} | ${'trigintillion'} - ${41} | ${'quadragintillion'} - ${51} | ${'quinquagintillion'} - ${61} | ${'sexagintillion'} - ${71} | ${'septuagintillion'} - ${81} | ${'octogintillion'} - ${91} | ${'nonagintillion'} + ${11n} | ${'decillion'} + ${21n} | ${'vigintillion'} + ${31n} | ${'trigintillion'} + ${41n} | ${'quadragintillion'} + ${51n} | ${'quinquagintillion'} + ${61n} | ${'sexagintillion'} + ${71n} | ${'septuagintillion'} + ${81n} | ${'octogintillion'} + ${91n} | ${'nonagintillion'} `('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) + expect(getShortKiloName(thousandPower)).toBe(name) }) test.each` thousandPower | name - ${101} | ${'centillion'} - ${201} | ${'duocentillion'} - ${301} | ${'trecentillion'} - ${401} | ${'quadringentillion'} - ${501} | ${'quingentillion'} - ${601} | ${'sescentillion'} - ${701} | ${'septingentillion'} - ${801} | ${'octingentillion'} - ${901} | ${'nongentillion'} + ${101n} | ${'centillion'} + ${201n} | ${'duocentillion'} + ${301n} | ${'trecentillion'} + ${401n} | ${'quadringentillion'} + ${501n} | ${'quingentillion'} + ${601n} | ${'sescentillion'} + ${701n} | ${'septingentillion'} + ${801n} | ${'octingentillion'} + ${901n} | ${'nongentillion'} `('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) + expect(getShortKiloName(thousandPower)).toBe(name) }) test.each` thousandPower | name - ${1001} | ${'milliatillion'} - ${2001} | ${'duomilliatillion'} - ${3001} | ${'tremilliatillion'} - ${4001} | ${'quattuormilliatillion'} - ${5001} | ${'quinmilliatillion'} - ${6001} | ${'sexmilliatillion'} - ${7001} | ${'septenmilliatillion'} - ${8001} | ${'octomilliatillion'} - ${9001} | ${'novemmilliatillion'} + ${1001n} | ${'milliatillion'} + ${2001n} | ${'duomilliatillion'} + ${3001n} | ${'tremilliatillion'} + ${4001n} | ${'quattuormilliatillion'} + ${5001n} | ${'quinmilliatillion'} + ${6001n} | ${'sexmilliatillion'} + ${7001n} | ${'septenmilliatillion'} + ${8001n} | ${'octomilliatillion'} + ${9001n} | ${'novemmilliatillion'} `('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) + expect(getShortKiloName(thousandPower)).toBe(name) }) test.each` thousandPower | name - ${10001} | ${'decmilliatillion'} - ${20001} | ${'viginmilliatillion'} - ${30001} | ${'triginmilliatillion'} - ${40001} | ${'quadraginmilliatillion'} - ${50001} | ${'quinquaginmilliatillion'} - ${60001} | ${'sexaginmilliatillion'} - ${70001} | ${'septuaginmilliatillion'} - ${80001} | ${'octoginmilliatillion'} - ${90001} | ${'nonaginmilliatillion'} + ${10001n} | ${'decmilliatillion'} + ${20001n} | ${'viginmilliatillion'} + ${30001n} | ${'triginmilliatillion'} + ${40001n} | ${'quadraginmilliatillion'} + ${50001n} | ${'quinquaginmilliatillion'} + ${60001n} | ${'sexaginmilliatillion'} + ${70001n} | ${'septuaginmilliatillion'} + ${80001n} | ${'octoginmilliatillion'} + ${90001n} | ${'nonaginmilliatillion'} `('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) + expect(getShortKiloName(thousandPower)).toBe(name) }) test.each` thousandPower | name - ${100001} | ${'cenmilliatillion'} - ${200001} | ${'duocenmilliatillion'} - ${300001} | ${'trecenmilliatillion'} - ${400001} | ${'quadringenmilliatillion'} - ${500001} | ${'quingenmilliatillion'} - ${600001} | ${'sescenmilliatillion'} - ${700001} | ${'septingenmilliatillion'} - ${800001} | ${'octingenmilliatillion'} - ${900001} | ${'nongenmilliatillion'} + ${100001n} | ${'cenmilliatillion'} + ${200001n} | ${'duocenmilliatillion'} + ${300001n} | ${'trecenmilliatillion'} + ${400001n} | ${'quadringenmilliatillion'} + ${500001n} | ${'quingenmilliatillion'} + ${600001n} | ${'sescenmilliatillion'} + ${700001n} | ${'septingenmilliatillion'} + ${800001n} | ${'octingenmilliatillion'} + ${900001n} | ${'nongenmilliatillion'} `('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) + expect(getShortKiloName(thousandPower)).toBe(name) }) test.each` thousandPower | name - ${1000001} | ${'milliamilliatillion'} - ${2000001} | ${'duomilliamilliatillion'} - ${3000001} | ${'tremilliamilliatillion'} - ${4000001} | ${'quattuormilliamilliatillion'} - ${5000001} | ${'quinmilliamilliatillion'} - ${6000001} | ${'sexmilliamilliatillion'} - ${7000001} | ${'septenmilliamilliatillion'} - ${8000001} | ${'octomilliamilliatillion'} - ${9000001} | ${'novemmilliamilliatillion'} + ${1000001n} | ${'milliamilliatillion'} + ${2000001n} | ${'duomilliamilliatillion'} + ${3000001n} | ${'tremilliamilliatillion'} + ${4000001n} | ${'quattuormilliamilliatillion'} + ${5000001n} | ${'quinmilliamilliatillion'} + ${6000001n} | ${'sexmilliamilliatillion'} + ${7000001n} | ${'septenmilliamilliatillion'} + ${8000001n} | ${'octomilliamilliatillion'} + ${9000001n} | ${'novemmilliamilliatillion'} `('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { - expect(getKiloName(thousandPower)).toBe(name) + expect(getShortKiloName(thousandPower)).toBe(name) }) diff --git a/src/systems/en/getShortKiloName.ts b/src/systems/en/getShortKiloName.ts index 0ddc40d..b5a7582 100644 --- a/src/systems/en/getShortKiloName.ts +++ b/src/systems/en/getShortKiloName.ts @@ -1,18 +1,18 @@ -import { GetKiloName } from '../../NumberSystem' -import NAMES from './names.json' +import { GetKiloName, Digit } from '../../common' +import NAMES from './names' import getKiloCombiningPrefix from './base/kilo/combiningPrefix' const getKiloName: GetKiloName = (thousandPower) => { - if (thousandPower === 0) { + if (thousandPower === 0n) { return '' } - if (thousandPower === 1) { + if (thousandPower === 1n) { return NAMES.thousand } - const kilo = thousandPower - 1 - const kiloHundreds = Math.floor(kilo / 100) - const kiloTens = Math.floor((kilo / 10) % 10) - const kiloOnes = Math.floor(kilo % 10) + const kilo = thousandPower - 1n + const kiloHundreds = kilo / 100n + const kiloTens = (Number(kilo / 10n) % 10) as Digit + const kiloOnes = (Number(kilo) % 10) as Digit return getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes) + NAMES.kiloEvenSuffix } diff --git a/src/systems/en/index.ts b/src/systems/en/index.ts new file mode 100644 index 0000000..aee2383 --- /dev/null +++ b/src/systems/en/index.ts @@ -0,0 +1,18 @@ +import { NumberSystem } from '../../common' +import getKiloCount from './getKiloCount' +import getLongKiloName from './getLongKiloName' +import getEuropeanLongKiloName from './getEuropeanLongKiloName' +import getShortKiloName from './getShortKiloName' +import joinKilo from './joinKilo' + +const numberSystem: NumberSystem = { + getKiloCount, + getKiloName: { + short: getShortKiloName, + long: getLongKiloName, + europeanLong: getEuropeanLongKiloName, + }, + joinKilo, +} + +export default numberSystem diff --git a/src/systems/en/joinKilo.ts b/src/systems/en/joinKilo.ts new file mode 100644 index 0000000..ecdbba5 --- /dev/null +++ b/src/systems/en/joinKilo.ts @@ -0,0 +1,5 @@ +import { JoinKilo } from '../../common' + +const joinKilo: JoinKilo = (kiloCount, kiloName) => (kiloName ? [kiloCount, kiloName].join(' ') : kiloCount) + +export default joinKilo diff --git a/src/systems/en/names.json b/src/systems/en/names.json deleted file mode 100644 index fe5fa34..0000000 --- a/src/systems/en/names.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "units": [ - "zero", - "one", - "two", - "three", - "four", - "five", - "six", - "seven", - "eight", - "nine" - ], - "tenPlus": [ - "ten", - "eleven", - "twelve", - "thirteen", - "fourteen", - "fifteen", - "sixteen", - "seventeen", - "eighteen", - "nineteen" - ], - "tenTimes": [ - "zero", - "ten", - "twenty", - "thirty", - "forty", - "fifty", - "sixty", - "seventy", - "eighty", - "ninety" - ], - "hundred": "hundred", - "thousand": "thousand", - "kiloSpecialUnits": [ - "", - "m", - "b", - "tr", - "quadr", - "quin", - "sex", - "sept", - "oct", - "non" - ], - "kiloUnits": [ - "", - "un", - "duo", - "tre", - "quattuor", - "quin", - "sex", - "septen", - "octo", - "novem" - ], - "kiloTens": [ - "", - "dec", - "vigin", - "trigin", - "quadragin", - "quinquagin", - "sexagin", - "septuagin", - "octogin", - "nonagin" - ], - "kiloHundreds": [ - "", - "cen", - "duocen", - "trecen", - "quadringen", - "quingen", - "sescen", - "septingen", - "octingen", - "nongen" - ], - "kiloThousand": "millia", - "kiloEvenSuffix": "llion", - "kiloOddSuffix": "lliard", - "and": "and" -} diff --git a/src/systems/en/names.ts b/src/systems/en/names.ts new file mode 100644 index 0000000..c562cae --- /dev/null +++ b/src/systems/en/names.ts @@ -0,0 +1,30 @@ +import { NumberSystemNameTable } from '../../common' + +const names: NumberSystemNameTable = { + units: ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'], + tenPlus: [ + 'ten', + 'eleven', + 'twelve', + 'thirteen', + 'fourteen', + 'fifteen', + 'sixteen', + 'seventeen', + 'eighteen', + 'nineteen', + ], + tenTimes: ['zero', 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'], + hundred: 'hundred', + thousand: 'thousand', + kiloSpecialUnits: ['', 'm', 'b', 'tr', 'quadr', 'quin', 'sex', 'sept', 'oct', 'non'], + kiloUnits: ['', 'un', 'duo', 'tre', 'quattuor', 'quin', 'sex', 'septen', 'octo', 'novem'], + kiloTens: ['', 'dec', 'vigin', 'trigin', 'quadragin', 'quinquagin', 'sexagin', 'septuagin', 'octogin', 'nonagin'], + kiloHundreds: ['', 'cen', 'duocen', 'trecen', 'quadringen', 'quingen', 'sescen', 'septingen', 'octingen', 'nongen'], + kiloThousand: 'millia', + kiloEvenSuffix: 'llion', + kiloOddSuffix: 'lliard', + and: 'and', +} + +export default names diff --git a/src/systems/tl/base/hundredTimes.ts b/src/systems/tl/base/hundredTimes.ts index 25df6cd..e189076 100644 --- a/src/systems/tl/base/hundredTimes.ts +++ b/src/systems/tl/base/hundredTimes.ts @@ -1,7 +1,8 @@ -import NAMES from '../names.json' +import { Digit } from '../../../common' +import NAMES from '../names' interface HundredTimes { - (x100: number): string + (x100: Digit): string } /** @@ -19,7 +20,7 @@ const hundredTimes: HundredTimes = (x100) => { let infix: string let hundredSuffixCombining: string - switch (x100) { + switch (Number(x100)) { case 1: hundredFactorCombining = hundredFactor.slice(1) infix = 'n' diff --git a/src/systems/tl/base/kilo/combiningPrefix.test.ts b/src/systems/tl/base/kilo/combiningPrefix.test.ts index 53361b0..ba14c36 100644 --- a/src/systems/tl/base/kilo/combiningPrefix.test.ts +++ b/src/systems/tl/base/kilo/combiningPrefix.test.ts @@ -8,8 +8,8 @@ it('should be a callable', () => { expect(typeof combiningPrefix).toBe('function') }) -it('should accept 4 arguments', () => { - expect(combiningPrefix).toHaveLength(4) +it('should accept a minimum of 3 arguments', () => { + expect(combiningPrefix).toHaveLength(3) }) describe('on 0 in hundreds place', () => { @@ -26,7 +26,7 @@ describe('on 0 in hundreds place', () => { ${8} | ${'8'} | ${'okti'} ${9} | ${'9'} | ${'noni'} `('should return "$name" on $display', ({ value, name }) => { - expect(combiningPrefix(0, 0, value)).toBe(name) + expect(combiningPrefix(0n, 0, value)).toBe(name) }) }) @@ -55,22 +55,22 @@ describe('on 0 in hundreds place', () => { ${8} | ${'okto' + tensName} ${9} | ${'nobem' + tensName} `(`should return "$display" for ${tens}$ones`, ({ ones, display }) => { - expect(combiningPrefix(0, tens, ones)).toBe(display) + expect(combiningPrefix(0n, tens, ones)).toBe(display) }) }) }) describe.each` hundreds | hundredsName - ${1} | ${'sen'} - ${2} | ${'duwosen'} - ${3} | ${'tresen'} - ${4} | ${'kuwadringhen'} - ${5} | ${'kuwinghen'} - ${6} | ${'sesen'} - ${7} | ${'septinghen'} - ${8} | ${'oktinghen'} - ${9} | ${'nonghen'} + ${1n} | ${'sen'} + ${2n} | ${'duwosen'} + ${3n} | ${'tresen'} + ${4n} | ${'kuwadringhen'} + ${5n} | ${'kuwinghen'} + ${6n} | ${'sesen'} + ${7n} | ${'septinghen'} + ${8n} | ${'oktinghen'} + ${9n} | ${'nonghen'} `('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => { describe.each` tens | tensName @@ -105,74 +105,74 @@ describe.each` describe.each` hundredThousands | hundredThousandsName - ${1} | ${'sen'} - ${2} | ${'duwosen'} - ${3} | ${'tresen'} - ${4} | ${'kuwadringhen'} - ${5} | ${'kuwinghen'} - ${6} | ${'sesen'} - ${7} | ${'septinghen'} - ${8} | ${'oktinghen'} - ${9} | ${'nonghen'} + ${1n} | ${'sen'} + ${2n} | ${'duwosen'} + ${3n} | ${'tresen'} + ${4n} | ${'kuwadringhen'} + ${5n} | ${'kuwinghen'} + ${6n} | ${'sesen'} + ${7n} | ${'septinghen'} + ${8n} | ${'oktinghen'} + ${9n} | ${'nonghen'} `('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName }) => { describe.each` tenThousands | tenThousandsName - ${0} | ${''} - ${1} | ${'des'} - ${2} | ${'bihin'} - ${3} | ${'trihin'} - ${4} | ${'kuwadrahin'} - ${5} | ${'kuwinkuwahin'} - ${6} | ${'seksahin'} - ${7} | ${'septuwahin'} - ${8} | ${'oktohin'} - ${9} | ${'nonahin'} + ${0n} | ${''} + ${1n} | ${'des'} + ${2n} | ${'bihin'} + ${3n} | ${'trihin'} + ${4n} | ${'kuwadrahin'} + ${5n} | ${'kuwinkuwahin'} + ${6n} | ${'seksahin'} + ${7n} | ${'septuwahin'} + ${8n} | ${'oktohin'} + ${9n} | ${'nonahin'} `('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName }) => { test.each` thousands | display | name - ${0} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milyati'} - ${1000} | ${hundredThousands + '' + tenThousands + '1000'} | ${hundredThousandsName + 'un' + tenThousandsName + 'milyati'} - ${2000} | ${hundredThousands + '' + tenThousands + '2000'} | ${hundredThousandsName + 'duwo' + tenThousandsName + 'milyati'} - ${3000} | ${hundredThousands + '' + tenThousands + '3000'} | ${hundredThousandsName + 'tre' + tenThousandsName + 'milyati'} - ${4000} | ${hundredThousands + '' + tenThousands + '4000'} | ${hundredThousandsName + 'kuwatuwor' + tenThousandsName + 'milyati'} - ${5000} | ${hundredThousands + '' + tenThousands + '5000'} | ${hundredThousandsName + 'kuwin' + tenThousandsName + 'milyati'} - ${6000} | ${hundredThousands + '' + tenThousands + '6000'} | ${hundredThousandsName + 'seks' + tenThousandsName + 'milyati'} - ${7000} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milyati'} - ${8000} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'okto' + tenThousandsName + 'milyati'} - ${9000} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'nobem' + tenThousandsName + 'milyati'} + ${0n} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milyati'} + ${1000n} | ${hundredThousands + '' + tenThousands + '1000'} | ${hundredThousandsName + 'un' + tenThousandsName + 'milyati'} + ${2000n} | ${hundredThousands + '' + tenThousands + '2000'} | ${hundredThousandsName + 'duwo' + tenThousandsName + 'milyati'} + ${3000n} | ${hundredThousands + '' + tenThousands + '3000'} | ${hundredThousandsName + 'tre' + tenThousandsName + 'milyati'} + ${4000n} | ${hundredThousands + '' + tenThousands + '4000'} | ${hundredThousandsName + 'kuwatuwor' + tenThousandsName + 'milyati'} + ${5000n} | ${hundredThousands + '' + tenThousands + '5000'} | ${hundredThousandsName + 'kuwin' + tenThousandsName + 'milyati'} + ${6000n} | ${hundredThousands + '' + tenThousands + '6000'} | ${hundredThousandsName + 'seks' + tenThousandsName + 'milyati'} + ${7000n} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milyati'} + ${8000n} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'okto' + tenThousandsName + 'milyati'} + ${9000n} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'nobem' + tenThousandsName + 'milyati'} `(`should return "$name" for $display`, ({ thousands, name }) => { - const kiloHundreds = hundredThousands * 1000 + tenThousands * 100 + thousands / 100 + const kiloHundreds = hundredThousands * 1000n + tenThousands * 100n + thousands / 100n expect(combiningPrefix(kiloHundreds, 0, 0)).toBe(name) }) }) }) -it.each` +test.each` value | display | name - ${1} | ${'1000000'} | ${'milyamilyati'} - ${2} | ${'2000000'} | ${'duwomilyamilyati'} - ${3} | ${'3000000'} | ${'tremilyamilyati'} - ${4} | ${'4000000'} | ${'kuwatuwormilyamilyati'} - ${5} | ${'5000000'} | ${'kuwinmilyamilyati'} - ${6} | ${'6000000'} | ${'seksmilyamilyati'} - ${7} | ${'7000000'} | ${'septenmilyamilyati'} - ${8} | ${'8000000'} | ${'oktomilyamilyati'} - ${9} | ${'9000000'} | ${'nobemmilyamilyati'} + ${1n} | ${'1000000'} | ${'milyamilyati'} + ${2n} | ${'2000000'} | ${'duwomilyamilyati'} + ${3n} | ${'3000000'} | ${'tremilyamilyati'} + ${4n} | ${'4000000'} | ${'kuwatuwormilyamilyati'} + ${5n} | ${'5000000'} | ${'kuwinmilyamilyati'} + ${6n} | ${'6000000'} | ${'seksmilyamilyati'} + ${7n} | ${'7000000'} | ${'septenmilyamilyati'} + ${8n} | ${'8000000'} | ${'oktomilyamilyati'} + ${9n} | ${'9000000'} | ${'nobemmilyamilyati'} `('should return "$name" on $display', ({ value, name }) => { - expect(combiningPrefix(value * 10000, 0, 0)).toBe(name) + expect(combiningPrefix(value * 10000n, 0, 0)).toBe(name) }) -it.each` +test.each` value | display | name - ${1} | ${'1001000'} | ${'milyamilyaunmilyati'} - ${2} | ${'2002000'} | ${'duwomilyamilyaduwomilyati'} - ${3} | ${'3003000'} | ${'tremilyamilyatremilyati'} - ${4} | ${'4004000'} | ${'kuwatuwormilyamilyakuwatuwormilyati'} - ${5} | ${'5005000'} | ${'kuwinmilyamilyakuwinmilyati'} - ${6} | ${'6006000'} | ${'seksmilyamilyaseksmilyati'} - ${7} | ${'7007000'} | ${'septenmilyamilyaseptenmilyati'} - ${8} | ${'8008000'} | ${'oktomilyamilyaoktomilyati'} - ${9} | ${'9009000'} | ${'nobemmilyamilyanobemmilyati'} + ${1n} | ${'1001000'} | ${'milyamilyaunmilyati'} + ${2n} | ${'2002000'} | ${'duwomilyamilyaduwomilyati'} + ${3n} | ${'3003000'} | ${'tremilyamilyatremilyati'} + ${4n} | ${'4004000'} | ${'kuwatuwormilyamilyakuwatuwormilyati'} + ${5n} | ${'5005000'} | ${'kuwinmilyamilyakuwinmilyati'} + ${6n} | ${'6006000'} | ${'seksmilyamilyaseksmilyati'} + ${7n} | ${'7007000'} | ${'septenmilyamilyaseptenmilyati'} + ${8n} | ${'8008000'} | ${'oktomilyamilyaoktomilyati'} + ${9n} | ${'9009000'} | ${'nobemmilyamilyanobemmilyati'} `('should return "$name" on $display', ({ value, name }) => { - expect(combiningPrefix(value * 10010, 0, 0)).toBe(name) + expect(combiningPrefix(value * 10010n, 0, 0)).toBe(name) }) diff --git a/src/systems/tl/base/kilo/combiningPrefix.ts b/src/systems/tl/base/kilo/combiningPrefix.ts index 7901b61..f724c81 100644 --- a/src/systems/tl/base/kilo/combiningPrefix.ts +++ b/src/systems/tl/base/kilo/combiningPrefix.ts @@ -1,63 +1,74 @@ -import NAMES from '../../names.json' +import { Digit } from '../../../../common' +import NAMES from '../../names' import ones from './ones' import tens from './tens' import hundreds from './hundreds' interface CombiningPrefix { - (kiloHundreds: number, kiloTens: number, kiloOnes: number, kiloPower?: number): string + (kiloHundreds: bigint, kiloTens: Digit, kiloOnes: Digit, kiloPower?: bigint): string } -const combiningPrefix: CombiningPrefix = (kiloHundredsRaw, kiloTens, kiloOnes, kiloPower = 0) => { - let kiloHundreds = kiloHundredsRaw +const combiningPrefix: CombiningPrefix = (kiloHundreds, kiloTens, kiloOnes, kiloPower = 0n) => { + let currentKiloHundreds = kiloHundreds let prefix = '' - const isMillia = kiloHundredsRaw >= 10 + const isMillia = kiloHundreds >= 10n if (isMillia) { prefix += combiningPrefix( - Math.floor(kiloHundredsRaw / 1000), - Math.floor((kiloHundredsRaw / 100) % 10), - Math.floor((kiloHundredsRaw / 10) % 10), - kiloPower + 1, + kiloHundreds / 1000n, + (Number(kiloHundreds / 100n) % 10) as Digit, + (Number(kiloHundreds / 10n) % 10) as Digit, + kiloPower + 1n, ) - kiloHundreds = kiloHundredsRaw % 10 + currentKiloHundreds = kiloHundreds % 10n } - const hasHundreds = kiloHundreds > 0 + const hasHundreds = currentKiloHundreds > 0n if (hasHundreds) { - prefix += hundreds(kiloHundreds) + prefix += hundreds(Number(currentKiloHundreds % 10n) as Digit) } + const kiloTensNumber = Number(kiloTens) + const kiloOnesNumber = Number(kiloOnes) + 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))) + ((currentKiloHundreds === 0n && kiloTensNumber === 0 && kiloOnesNumber > 1) || + ((currentKiloHundreds > 0n || kiloTensNumber > 0) && kiloOnesNumber > 0) || + (currentKiloHundreds === 0n && + kiloTensNumber === 0 && + kiloOnesNumber === 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) } - if (kiloPower === 0 && kiloOnes > 0) { - const special = kiloHundreds === 0 && kiloTens === 0 + if (kiloPower === 0n && kiloOnesNumber) { + const special = currentKiloHundreds === 0n && kiloTensNumber === 0 prefix += ones(kiloOnes, special) - if (special && [5, 6].includes(kiloOnes)) { + if (special && [5, 6].includes(Number(kiloOnes))) { prefix += 't' } } - if (kiloTens > 0) { + if (kiloTensNumber > 0) { prefix += tens(kiloTens) } - if (kiloPower > 0) { - if (!(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 0)) { - for (let p = 0; p < kiloPower; p += 1) { + if (kiloPower > 0n) { + if (!(currentKiloHundreds === 0n && kiloTensNumber === 0 && kiloOnesNumber === 0)) { + for (let p = 0n; p < kiloPower; p += 1n) { prefix += NAMES.kiloThousand } } return prefix } - if ((kiloHundreds === 0 && kiloTens > 1) || (kiloHundreds > 0 && kiloTens !== 1) || kiloHundredsRaw >= 10) { + if ( + (currentKiloHundreds === 0n && kiloTensNumber > 1) || + (currentKiloHundreds > 0n && kiloTensNumber !== 1) || + kiloHundreds >= 10 + ) { prefix += 't' } return prefix + 'i' diff --git a/src/systems/tl/base/kilo/hundreds.ts b/src/systems/tl/base/kilo/hundreds.ts index 9d24831..b6ba02e 100644 --- a/src/systems/tl/base/kilo/hundreds.ts +++ b/src/systems/tl/base/kilo/hundreds.ts @@ -1,7 +1,8 @@ -import NAMES from '../../names.json' +import { Digit } from '../../../../common' +import NAMES from '../../names' interface Hundreds { - (kiloHundreds: number): string + (kiloHundreds: Digit): string } const hundreds: Hundreds = (kiloHundreds) => NAMES.kiloHundreds[kiloHundreds] diff --git a/src/systems/tl/base/kilo/ones.test.ts b/src/systems/tl/base/kilo/ones.test.ts index df46e8a..d531641 100644 --- a/src/systems/tl/base/kilo/ones.test.ts +++ b/src/systems/tl/base/kilo/ones.test.ts @@ -8,8 +8,8 @@ it('should be a callable', () => { expect(typeof ones).toBe('function') }) -it('should accept 2 arguments', () => { - expect(ones).toHaveLength(2) +it('should accept a minimum of 1 argument', () => { + expect(ones).toHaveLength(1) }) describe('on ordinary units', () => { diff --git a/src/systems/tl/base/kilo/ones.ts b/src/systems/tl/base/kilo/ones.ts index 0b11d0d..64dbffe 100644 --- a/src/systems/tl/base/kilo/ones.ts +++ b/src/systems/tl/base/kilo/ones.ts @@ -1,7 +1,8 @@ -import NAMES from '../../names.json' +import { Digit } from '../../../../common' +import NAMES from '../../names' interface Ones { - (kiloOnes: number, special: boolean): string + (kiloOnes: Digit, special: boolean): string } const ones: Ones = (kiloOnes, special = false) => diff --git a/src/systems/tl/base/kilo/tens.ts b/src/systems/tl/base/kilo/tens.ts index 54f9975..7cecc98 100644 --- a/src/systems/tl/base/kilo/tens.ts +++ b/src/systems/tl/base/kilo/tens.ts @@ -1,7 +1,8 @@ -import NAMES from '../../names.json' +import { Digit } from '../../../../common' +import NAMES from '../../names' interface Tens { - (kiloTens: number): string + (kiloTens: Digit): string } const tens: Tens = (kiloTens) => NAMES.kiloTens[kiloTens] diff --git a/src/systems/tl/base/ones.ts b/src/systems/tl/base/ones.ts index f63ea33..4c71085 100644 --- a/src/systems/tl/base/ones.ts +++ b/src/systems/tl/base/ones.ts @@ -1,7 +1,8 @@ -import NAMES from '../names.json' +import { Digit } from '../../../common' +import NAMES from '../names' interface Ones { - (x1: number): string + (x1: Digit): string } /** diff --git a/src/systems/tl/base/tenPlus.ts b/src/systems/tl/base/tenPlus.ts index ef92973..6c68999 100644 --- a/src/systems/tl/base/tenPlus.ts +++ b/src/systems/tl/base/tenPlus.ts @@ -1,7 +1,8 @@ -import NAMES from '../names.json' +import { Digit } from '../../../common' +import NAMES from '../names' interface TenPlus { - (ones: number): string + (ones: Digit): string } /** @@ -9,6 +10,6 @@ interface TenPlus { * @param {number} x1 - The number in the ones place. * @returns {string} The name of the number plus ten. */ -const tenPlus: TenPlus = (x1) => (x1 === 0 ? NAMES.tenTimes[1] : NAMES.tenPlus[x1]) +const tenPlus: TenPlus = (x1) => (Number(x1) === 0 ? NAMES.tenTimes[1] : NAMES.tenPlus[x1]) export default tenPlus diff --git a/src/systems/tl/base/tenTimes.ts b/src/systems/tl/base/tenTimes.ts index 7366877..9a616cc 100644 --- a/src/systems/tl/base/tenTimes.ts +++ b/src/systems/tl/base/tenTimes.ts @@ -1,7 +1,8 @@ -import NAMES from '../names.json' +import { Digit } from '../../../common' +import NAMES from '../names' interface TenTimes { - (x10: number): string + (x10: Digit): string } /** diff --git a/src/systems/tl/construct/tens.ts b/src/systems/tl/construct/tens.ts index 178670a..985b2fb 100644 --- a/src/systems/tl/construct/tens.ts +++ b/src/systems/tl/construct/tens.ts @@ -1,10 +1,11 @@ -import NAMES from '../names.json' +import { Digit } from '../../../common' +import NAMES from '../names' import ones from '../base/ones' import tenPlus from '../base/tenPlus' import getBaseTenTimesName from '../base/tenTimes' interface Tens { - (x10: number, x1: number): string + (x10: Digit, x1: Digit): string } const tens: Tens = (x10, x1) => { diff --git a/src/systems/tl/getKiloCount.test.ts b/src/systems/tl/getKiloCount.test.ts index c843238..a252c47 100644 --- a/src/systems/tl/getKiloCount.test.ts +++ b/src/systems/tl/getKiloCount.test.ts @@ -46,15 +46,15 @@ describe.each` test.each` ones | tenPlusName ${0} | ${' at sampu'} - ${1} | ${' labing-isa'} - ${2} | ${' labindalawa'} - ${3} | ${' labintatlo'} - ${4} | ${' labing-apat'} - ${5} | ${' labinlima'} - ${6} | ${' labing-anim'} - ${7} | ${' labimpito'} - ${8} | ${' labingwalo'} - ${9} | ${' labinsiyam'} + ${1} | ${' at labing-isa'} + ${2} | ${' at labindalawa'} + ${3} | ${' at labintatlo'} + ${4} | ${' at labing-apat'} + ${5} | ${' at labinlima'} + ${6} | ${' at labing-anim'} + ${7} | ${' at labimpito'} + ${8} | ${' at labingwalo'} + ${9} | ${' at labinsiyam'} `(`should return "${hundredsName}$tenPlusName" for ${hundreds}1$ones`, ({ ones, tenPlusName }) => { expect(getKiloCount(hundreds, 1, ones)).toBe([hundredsName, tenPlusName].join('')) }) diff --git a/src/systems/tl/getKiloCount.ts b/src/systems/tl/getKiloCount.ts index e35f683..06c8a9c 100644 --- a/src/systems/tl/getKiloCount.ts +++ b/src/systems/tl/getKiloCount.ts @@ -1,5 +1,5 @@ -import NAMES from './names.json' -import { GetKiloCount } from '../../NumberSystem' +import { GetKiloCount } from '../../common' +import NAMES from './names' import constructTens from './construct/tens' import hundredTimes from './base/hundredTimes' @@ -14,7 +14,7 @@ const getKiloCount: GetKiloCount = (x100, x10, x1) => { } return [hundredTimes(x100), NAMES.and, constructTens(0, x1)].join(' ') } - if (x1 === 0) { + if (x10 === 1 || x1 === 0) { return [hundredTimes(x100), NAMES.and, constructTens(x10, x1)].join(' ') } return [hundredTimes(x100), constructTens(x10, x1)].join(' ') diff --git a/src/systems/tl/getShortKiloName.test.ts b/src/systems/tl/getShortKiloName.test.ts new file mode 100644 index 0000000..7aebf26 --- /dev/null +++ b/src/systems/tl/getShortKiloName.test.ts @@ -0,0 +1,120 @@ +import getShortKiloName from './getShortKiloName' + +it('should exist', () => { + expect(getShortKiloName).toBeDefined() +}) + +it('should be a callable', () => { + expect(typeof getShortKiloName).toBe('function') +}) + +it('should accept 1 argument', () => { + expect(getShortKiloName).toHaveLength(1) +}) + +test.each` + thousandPower | name + ${0n} | ${''} + ${1n} | ${'libo'} + ${2n} | ${'milyon'} + ${3n} | ${'bilyon'} + ${4n} | ${'trilyon'} + ${5n} | ${'kuwadrilyon'} + ${6n} | ${'kuwintilyon'} + ${7n} | ${'sekstilyon'} + ${8n} | ${'septilyon'} + ${9n} | ${'oktilyon'} + ${10n} | ${'nonilyon'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getShortKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${11n} | ${'desilyon'} + ${21n} | ${'bihintilyon'} + ${31n} | ${'trihintilyon'} + ${41n} | ${'kuwadrahintilyon'} + ${51n} | ${'kuwinkuwahintilyon'} + ${61n} | ${'seksahintilyon'} + ${71n} | ${'septuwahintilyon'} + ${81n} | ${'oktohintilyon'} + ${91n} | ${'nonahintilyon'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getShortKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${101n} | ${'sentilyon'} + ${201n} | ${'duwosentilyon'} + ${301n} | ${'tresentilyon'} + ${401n} | ${'kuwadringhentilyon'} + ${501n} | ${'kuwinghentilyon'} + ${601n} | ${'sesentilyon'} + ${701n} | ${'septinghentilyon'} + ${801n} | ${'oktinghentilyon'} + ${901n} | ${'nonghentilyon'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getShortKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${1001n} | ${'milyatilyon'} + ${2001n} | ${'duwomilyatilyon'} + ${3001n} | ${'tremilyatilyon'} + ${4001n} | ${'kuwatuwormilyatilyon'} + ${5001n} | ${'kuwinmilyatilyon'} + ${6001n} | ${'seksmilyatilyon'} + ${7001n} | ${'septenmilyatilyon'} + ${8001n} | ${'oktomilyatilyon'} + ${9001n} | ${'nobemmilyatilyon'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getShortKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${10001n} | ${'desmilyatilyon'} + ${20001n} | ${'bihinmilyatilyon'} + ${30001n} | ${'trihinmilyatilyon'} + ${40001n} | ${'kuwadrahinmilyatilyon'} + ${50001n} | ${'kuwinkuwahinmilyatilyon'} + ${60001n} | ${'seksahinmilyatilyon'} + ${70001n} | ${'septuwahinmilyatilyon'} + ${80001n} | ${'oktohinmilyatilyon'} + ${90001n} | ${'nonahinmilyatilyon'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getShortKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${100001n} | ${'senmilyatilyon'} + ${200001n} | ${'duwosenmilyatilyon'} + ${300001n} | ${'tresenmilyatilyon'} + ${400001n} | ${'kuwadringhenmilyatilyon'} + ${500001n} | ${'kuwinghenmilyatilyon'} + ${600001n} | ${'sesenmilyatilyon'} + ${700001n} | ${'septinghenmilyatilyon'} + ${800001n} | ${'oktinghenmilyatilyon'} + ${900001n} | ${'nonghenmilyatilyon'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getShortKiloName(thousandPower)).toBe(name) +}) + +test.each` + thousandPower | name + ${1000001n} | ${'milyamilyatilyon'} + ${2000001n} | ${'duwomilyamilyatilyon'} + ${3000001n} | ${'tremilyamilyatilyon'} + ${4000001n} | ${'kuwatuwormilyamilyatilyon'} + ${5000001n} | ${'kuwinmilyamilyatilyon'} + ${6000001n} | ${'seksmilyamilyatilyon'} + ${7000001n} | ${'septenmilyamilyatilyon'} + ${8000001n} | ${'oktomilyamilyatilyon'} + ${9000001n} | ${'nobemmilyamilyatilyon'} +`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => { + expect(getShortKiloName(thousandPower)).toBe(name) +}) diff --git a/src/systems/tl/getShortKiloName.ts b/src/systems/tl/getShortKiloName.ts new file mode 100644 index 0000000..b5a7582 --- /dev/null +++ b/src/systems/tl/getShortKiloName.ts @@ -0,0 +1,20 @@ +import { GetKiloName, Digit } from '../../common' +import NAMES from './names' +import getKiloCombiningPrefix from './base/kilo/combiningPrefix' + +const getKiloName: GetKiloName = (thousandPower) => { + if (thousandPower === 0n) { + return '' + } + if (thousandPower === 1n) { + return NAMES.thousand + } + const kilo = thousandPower - 1n + const kiloHundreds = kilo / 100n + const kiloTens = (Number(kilo / 10n) % 10) as Digit + const kiloOnes = (Number(kilo) % 10) as Digit + + return getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes) + NAMES.kiloEvenSuffix +} + +export default getKiloName diff --git a/src/systems/tl/index.ts b/src/systems/tl/index.ts new file mode 100644 index 0000000..c8b4655 --- /dev/null +++ b/src/systems/tl/index.ts @@ -0,0 +1,14 @@ +import { NumberSystem } from '../../common' +import getKiloCount from './getKiloCount' +import getShortKiloName from './getShortKiloName' +import joinKilo from './joinKilo' + +const numberSystem: NumberSystem = { + getKiloCount, + getKiloName: { + short: getShortKiloName, + }, + joinKilo, +} + +export default numberSystem diff --git a/src/systems/tl/joinKilo.ts b/src/systems/tl/joinKilo.ts new file mode 100644 index 0000000..c3db47a --- /dev/null +++ b/src/systems/tl/joinKilo.ts @@ -0,0 +1,18 @@ +import { JoinKilo } from '../../common' + +const joinKilo: JoinKilo = (kiloCount, kiloName) => { + const kiloCountLastLetter = kiloCount.slice(-1) + let kiloCountSuffix = ' na ' + + if (['a', 'o'].includes(kiloCountLastLetter)) { + kiloCountSuffix = 'ng ' + } + + if ('n' === kiloCountLastLetter) { + kiloCountSuffix = 'g ' + } + + return [kiloCount, kiloCountSuffix, kiloName].join('') +} + +export default joinKilo diff --git a/src/systems/tl/names.json b/src/systems/tl/names.json deleted file mode 100644 index b18de9a..0000000 --- a/src/systems/tl/names.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "units": [ - "sero", - "isa", - "dalawa", - "tatlo", - "apat", - "lima", - "anim", - "pito", - "walo", - "siyam" - ], - "tenPlus": [ - "sampu", - "labing-isa", - "labindalawa", - "labintatlo", - "labing-apat", - "labinlima", - "labing-anim", - "labimpito", - "labingwalo", - "labinsiyam" - ], - "tenTimes": [ - "sero", - "sampu", - "dalawampu", - "tatlumpu", - "apatnapu", - "limampu", - "animnapu", - "pitumpu", - "walumpu", - "siyamnapu" - ], - "hundred": "daan", - "thousand": "libo", - "kiloSpecialUnits": [ - "", - "m", - "b", - "tr", - "kuwadr", - "kuwin", - "seks", - "sept", - "okt", - "non" - ], - "kiloUnits": [ - "", - "un", - "duwo", - "tre", - "kuwatuwor", - "kuwin", - "seks", - "septen", - "okto", - "nobem" - ], - "kiloTens": [ - "", - "des", - "bihin", - "trihin", - "kuwadrahin", - "kuwinkuwahin", - "seksahin", - "septuwahin", - "oktohin", - "nonahin" - ], - "kiloHundreds": [ - "", - "sen", - "duwosen", - "tresen", - "kuwadringhen", - "kuwinghen", - "sesen", - "septinghen", - "oktinghen", - "nonghen" - ], - "kiloThousand": "milya", - "kiloEvenSuffix": "lyon", - "kiloOddSuffix": "lyard", - "and": "at" -} diff --git a/src/systems/tl/names.ts b/src/systems/tl/names.ts new file mode 100644 index 0000000..d477661 --- /dev/null +++ b/src/systems/tl/names.ts @@ -0,0 +1,63 @@ +import { NumberSystemNameTable } from '../../common' + +const names: NumberSystemNameTable = { + units: ['sero', 'isa', 'dalawa', 'tatlo', 'apat', 'lima', 'anim', 'pito', 'walo', 'siyam'], + tenPlus: [ + 'sampu', + 'labing-isa', + 'labindalawa', + 'labintatlo', + 'labing-apat', + 'labinlima', + 'labing-anim', + 'labimpito', + 'labingwalo', + 'labinsiyam', + ], + tenTimes: [ + 'sero', + 'sampu', + 'dalawampu', + 'tatlumpu', + 'apatnapu', + 'limampu', + 'animnapu', + 'pitumpu', + 'walumpu', + 'siyamnapu', + ], + hundred: 'daan', + thousand: 'libo', + kiloSpecialUnits: ['', 'm', 'b', 'tr', 'kuwadr', 'kuwin', 'seks', 'sept', 'okt', 'non'], + kiloUnits: ['', 'un', 'duwo', 'tre', 'kuwatuwor', 'kuwin', 'seks', 'septen', 'okto', 'nobem'], + kiloTens: [ + '', + 'des', + 'bihin', + 'trihin', + 'kuwadrahin', + 'kuwinkuwahin', + 'seksahin', + 'septuwahin', + 'oktohin', + 'nonahin', + ], + kiloHundreds: [ + '', + 'sen', + 'duwosen', + 'tresen', + 'kuwadringhen', + 'kuwinghen', + 'sesen', + 'septinghen', + 'oktinghen', + 'nonghen', + ], + kiloThousand: 'milya', + kiloEvenSuffix: 'lyon', + kiloOddSuffix: 'lyard', + and: 'at', +} + +export default names diff --git a/tsconfig.json b/tsconfig.json index fe80e5e..6c6b3a1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,7 @@ "include": ["src", "types"], "compilerOptions": { "module": "esnext", + "target": "ES2020", "lib": ["dom", "esnext"], "importHelpers": true, "declaration": true,