Browse Source

Implement tests for streams

Add basic parsing for streams and values.
master
TheoryOfNekomata 3 years ago
parent
commit
d17a77675d
69 changed files with 457 additions and 585 deletions
  1. +1
    -0
      .gitignore
  2. +1
    -0
      package.json
  3. +43
    -0
      src/Converter.ts
  4. +45
    -0
      src/ConverterStream.ts
  5. +3
    -3
      src/NumberSystem.ts
  6. +14
    -0
      src/NumberSystemNameTable.ts
  7. +11
    -0
      src/common.ts
  8. +0
    -14
      src/common/NumberSystemNameTable.ts
  9. +0
    -0
      src/common/interfaces.ts
  10. +3
    -3
      src/index.ts
  11. +1
    -1
      src/systems/de/base/hundredTimes.test.ts
  12. +1
    -8
      src/systems/de/base/hundredTimes.ts
  13. +13
    -22
      src/systems/de/base/kilo/combiningPrefix.test.ts
  14. +12
    -55
      src/systems/de/base/kilo/combiningPrefix.ts
  15. +1
    -1
      src/systems/de/base/kilo/hundreds.test.ts
  16. +1
    -1
      src/systems/de/base/kilo/hundreds.ts
  17. +2
    -2
      src/systems/de/base/kilo/ones.test.ts
  18. +3
    -6
      src/systems/de/base/kilo/ones.ts
  19. +1
    -1
      src/systems/de/base/kilo/tens.test.ts
  20. +1
    -1
      src/systems/de/base/kilo/tens.ts
  21. +1
    -2
      src/systems/de/base/ones.test.ts
  22. +1
    -1
      src/systems/de/base/tenPlus.test.ts
  23. +1
    -1
      src/systems/de/base/tenTimes.test.ts
  24. +24
    -24
      src/systems/de/construct/tens.test.ts
  25. +2
    -11
      src/systems/de/construct/tens.ts
  26. +7
    -7
      src/systems/de/getLongKiloName.test.ts
  27. +7
    -15
      src/systems/de/getLongKiloName.ts
  28. +2
    -2
      src/systems/en.ts
  29. +1
    -1
      src/systems/en/base/hundredTimes.test.ts
  30. +2
    -8
      src/systems/en/base/hundredTimes.ts
  31. +13
    -22
      src/systems/en/base/kilo/combiningPrefix.test.ts
  32. +12
    -55
      src/systems/en/base/kilo/combiningPrefix.ts
  33. +1
    -1
      src/systems/en/base/kilo/hundreds.test.ts
  34. +1
    -1
      src/systems/en/base/kilo/hundreds.ts
  35. +2
    -2
      src/systems/en/base/kilo/ones.test.ts
  36. +3
    -6
      src/systems/en/base/kilo/ones.ts
  37. +1
    -1
      src/systems/en/base/kilo/tens.test.ts
  38. +1
    -1
      src/systems/en/base/kilo/tens.ts
  39. +1
    -2
      src/systems/en/base/ones.test.ts
  40. +1
    -1
      src/systems/en/base/tenPlus.test.ts
  41. +1
    -1
      src/systems/en/base/tenTimes.test.ts
  42. +25
    -28
      src/systems/en/construct/tens.test.ts
  43. +2
    -10
      src/systems/en/construct/tens.ts
  44. +10
    -20
      src/systems/en/getKiloCount.test.ts
  45. +3
    -11
      src/systems/en/getKiloCount.ts
  46. +7
    -7
      src/systems/en/getLongKiloName.test.ts
  47. +6
    -14
      src/systems/en/getLongKiloName.ts
  48. +7
    -7
      src/systems/en/getShortKiloName.test.ts
  49. +4
    -8
      src/systems/en/getShortKiloName.ts
  50. +1
    -1
      src/systems/tl/base/hundredTimes.test.ts
  51. +1
    -6
      src/systems/tl/base/hundredTimes.ts
  52. +13
    -22
      src/systems/tl/base/kilo/combiningPrefix.test.ts
  53. +12
    -55
      src/systems/tl/base/kilo/combiningPrefix.ts
  54. +1
    -1
      src/systems/tl/base/kilo/hundreds.test.ts
  55. +1
    -1
      src/systems/tl/base/kilo/hundreds.ts
  56. +2
    -2
      src/systems/tl/base/kilo/ones.test.ts
  57. +3
    -6
      src/systems/tl/base/kilo/ones.ts
  58. +1
    -1
      src/systems/tl/base/kilo/tens.test.ts
  59. +1
    -1
      src/systems/tl/base/kilo/tens.ts
  60. +1
    -2
      src/systems/tl/base/ones.test.ts
  61. +1
    -1
      src/systems/tl/base/tenPlus.test.ts
  62. +1
    -1
      src/systems/tl/base/tenTimes.test.ts
  63. +25
    -28
      src/systems/tl/construct/tens.test.ts
  64. +2
    -13
      src/systems/tl/construct/tens.ts
  65. +20
    -33
      src/systems/tl/getKiloCount.test.ts
  66. +5
    -23
      src/systems/tl/getKiloCount.ts
  67. +54
    -0
      tests/Converter.test.ts
  68. +1
    -0
      tests/input/million.txt
  69. +5
    -0
      yarn.lock

+ 1
- 0
.gitignore View File

@@ -90,3 +90,4 @@ dist
.yarn/unplugged
.yarn/build-state.yml
.pnp.*
tests/output

+ 1
- 0
package.json View File

@@ -27,6 +27,7 @@
"author": "TheoryOfNekomata <allan.crisostomo@outlook.com> (https://modal.sh)",
"module": "dist/number-name.esm.js",
"devDependencies": {
"@types/node": "^14.6.0",
"fast-check": "^2.1.0",
"husky": "^4.2.5",
"tsdx": "^0.13.2",


+ 43
- 0
src/Converter.ts View File

@@ -0,0 +1,43 @@
import NumberSystem from './NumberSystem'
import ConverterStream from './ConverterStream'
import { ReadStreamOptions, ConvertOptions } from './common'

export default class Converter {
constructor(private readonly system: NumberSystem) {}

convert(value: string | number | bigint, options: ConvertOptions) {
let converted: string[] = []
switch (typeof value!) {
case 'string':
return ''
case 'bigint':
case 'number':
let current = value as number
let thousandPower = 0
while (current > 0) {
const hundreds = Math.floor((current % 1000) / 100)
const tens = Math.floor((current % 100) / 10)
const ones = Math.floor(current % 10)
if (!(ones === 0 && tens === 0 && hundreds === 0)) {
if (thousandPower > 0) {
const { scale = 'short' } = options
converted.unshift(this.system.getKiloName[scale!]!(thousandPower))
}
converted.unshift(this.system.getKiloCount(hundreds, tens, ones))
}

thousandPower = thousandPower + 1
current = Math.floor(current / 1000)
}
return converted.join(' ')
default:
break
}
throw TypeError('Invalid argument passed to value.')
}

readStream(options: ReadStreamOptions): ConverterStream {
const { scale = 'short', encoding = 'utf-8' } = options
return new ConverterStream(this.system, { scale, encoding })
}
}

+ 45
- 0
src/ConverterStream.ts View File

@@ -0,0 +1,45 @@
import { Transform } from 'stream'
import NumberSystem from './NumberSystem'
import { ReadStreamOptions } from './common'

export default class ConverterStream extends Transform {
private thousandPower: number = 0

constructor(private readonly system: NumberSystem, private readonly options: ReadStreamOptions) {
super()
this.thousandPower = 0
}

_transform(chunk: any, _encoding: BufferEncoding, callback: Function) {
const { scale, encoding } = this.options

const [ones = 0, tens = 0, hundreds = 0] = chunk
.toString(encoding!)
.split('')
.filter((s: string) => /[0-9]/.test(s))
.map((d: string) => Number(d)) // todo use encoding

if (!(ones === 0 && tens === 0 && hundreds === 0)) {
if (this.thousandPower > 0) {
this.push(
this.system.getKiloName[scale!]!(this.thousandPower)
.split('')
.reverse()
.join(''),
)
this.push(' ')
}
this.push(
this.system
.getKiloCount(hundreds, tens, ones)
.split('')
.reverse()
.join(''),
)
this.push(' ')
}

this.thousandPower = this.thousandPower + 1
callback()
}
}

src/common/NumberSystem.ts → src/NumberSystem.ts View File

@@ -2,9 +2,9 @@ export type GetKiloCount = (hundreds: number, tens: number, ones: number) => str
export type GetKiloName = (thousandPower: number) => string

export default interface NumberSystem {
getKiloCount: GetKiloCount,
getKiloCount: GetKiloCount
getKiloName: {
short?: GetKiloName,
long?: GetKiloName,
short?: GetKiloName
long?: GetKiloName
}
}

+ 14
- 0
src/NumberSystemNameTable.ts View File

@@ -0,0 +1,14 @@
export default interface NumberSystemNameTable {
units: string[10]
tenPlus: string[10]
tenTimes: string[10]
hundred: string
thousand: string
kiloSpecialUnits: string[10]
kiloUnits: string[10]
kiloTens: string[10]
kiloHundreds: string[10]
kiloThousand: string
kiloEvenSuffix: string
kiloOddSuffix: string
}

+ 11
- 0
src/common.ts View File

@@ -0,0 +1,11 @@
export type Scale = 'long' | 'short'

export interface ConvertOptions {
scale?: Scale
}

export interface StreamOptions {
encoding?: BufferEncoding
}

export type ReadStreamOptions = ConvertOptions & StreamOptions

+ 0
- 14
src/common/NumberSystemNameTable.ts View File

@@ -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,
}

+ 0
- 0
src/common/interfaces.ts View File


+ 3
- 3
src/index.ts View File

@@ -1,3 +1,3 @@
export default () => {
throw Error('Not yet implemented!')
}
import Converter from './Converter'
export default Converter

+ 1
- 1
src/systems/de/base/hundredTimes.test.ts View File

@@ -23,6 +23,6 @@ test.each`
${7} | ${'700'} | ${'siebenhundert'}
${8} | ${'800'} | ${'achthundert'}
${9} | ${'900'} | ${'neunhundert'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(hundredTimes(value)).toBe(name)
})

+ 1
- 8
src/systems/de/base/hundredTimes.ts View File

@@ -9,13 +9,6 @@ interface HundredTimes {
* @param {number} x100 - The number in the hundreds place.
* @returns {string} The name of the number in the hundreds place.
*/
const hundredTimes: HundredTimes = (x100) => (
x100 === 0
? NAMES.units[0]
: [
NAMES.units[x100],
NAMES.hundred,
].join('')
)
const hundredTimes: HundredTimes = (x100) => (x100 === 0 ? NAMES.units[0] : [NAMES.units[x100], NAMES.hundred].join(''))

export default hundredTimes

+ 13
- 22
src/systems/de/base/kilo/combiningPrefix.test.ts View File

@@ -25,7 +25,7 @@ describe('on 0 in hundreds place', () => {
${7} | ${'7'} | ${'septi'}
${8} | ${'8'} | ${'octi'}
${9} | ${'9'} | ${'noni'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(0, 0, value)).toBe(name)
})
})
@@ -41,7 +41,7 @@ describe('on 0 in hundreds place', () => {
${7} | ${'septuaginti'}
${8} | ${'octoginti'}
${9} | ${'nonaginti'}
`('on $tens in tens place', ({ tens, tensName, }) => {
`('on $tens in tens place', ({ tens, tensName }) => {
test.each`
ones | display
${0} | ${tensName}
@@ -54,7 +54,7 @@ describe('on 0 in hundreds place', () => {
${7} | ${'septen' + tensName}
${8} | ${'octo' + tensName}
${9} | ${'novem' + tensName}
`(`should return "$display" for ${tens}$ones`, ({ ones, display, }) => {
`(`should return "$display" for ${tens}$ones`, ({ ones, display }) => {
expect(combiningPrefix(0, tens, ones)).toBe(display)
})
})
@@ -71,7 +71,7 @@ describe.each`
${7} | ${'septingen'}
${8} | ${'octingen'}
${9} | ${'nongen'}
`('on $hundreds in hundreds place', ({ hundreds, hundredsName, }) => {
`('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => {
describe.each`
tens | tensName
${0} | ${'ti'}
@@ -84,7 +84,7 @@ describe.each`
${7} | ${'septuaginti'}
${8} | ${'octoginti'}
${9} | ${'nonaginti'}
`('on $tens in tens place', ({ tens, tensName, }) => {
`('on $tens in tens place', ({ tens, tensName }) => {
test.each`
ones | display
${0} | ${hundredsName + tensName}
@@ -97,7 +97,7 @@ describe.each`
${7} | ${hundredsName + 'septen' + tensName}
${8} | ${hundredsName + 'octo' + tensName}
${9} | ${hundredsName + 'novem' + tensName}
`(`should return "$display" for ${hundreds}${tens}$ones`, ({ ones, display, }) => {
`(`should return "$display" for ${hundreds}${tens}$ones`, ({ ones, display }) => {
expect(combiningPrefix(hundreds, tens, ones)).toBe(display)
})
})
@@ -114,7 +114,7 @@ describe.each`
${7} | ${'septingen'}
${8} | ${'octingen'}
${9} | ${'nongen'}
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName, }) => {
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName }) => {
describe.each`
tenThousands | tenThousandsName
${0} | ${''}
@@ -127,7 +127,7 @@ describe.each`
${7} | ${'septuagin'}
${8} | ${'octogin'}
${9} | ${'nonagin'}
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName, }) => {
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName }) => {
test.each`
thousands | display | name
${0} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milliati'}
@@ -140,17 +140,9 @@ describe.each`
${7000} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milliati'}
${8000} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'octo' + tenThousandsName + 'milliati'}
${9000} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'novem' + tenThousandsName + 'milliati'}
`(`should return "$name" for $display`, ({ thousands, name, }) => {
const kiloHundreds = (
hundredThousands * 1000
+ tenThousands * 100
+ thousands / 100
)
expect(combiningPrefix(
kiloHundreds,
0,
0,
)).toBe(name)
`(`should return "$name" for $display`, ({ thousands, name }) => {
const kiloHundreds = hundredThousands * 1000 + tenThousands * 100 + thousands / 100
expect(combiningPrefix(kiloHundreds, 0, 0)).toBe(name)
})
})
})
@@ -166,7 +158,7 @@ test.each`
${7} | ${'7000000'} | ${'septenmilliamilliati'}
${8} | ${'8000000'} | ${'octomilliamilliati'}
${9} | ${'9000000'} | ${'novemmilliamilliati'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(value * 10000, 0, 0)).toBe(name)
})

@@ -181,7 +173,6 @@ test.each`
${7} | ${'7007000'} | ${'septenmilliamilliaseptenmilliati'}
${8} | ${'8008000'} | ${'octomilliamilliaoctomilliati'}
${9} | ${'9009000'} | ${'novemmilliamillianovemmilliati'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(value * 10010, 0, 0)).toBe(name)
})


+ 12
- 55
src/systems/de/base/kilo/combiningPrefix.ts View File

@@ -4,20 +4,10 @@ import tens from './tens'
import hundreds from './hundreds'

interface CombiningPrefix {
(
kiloHundreds: number,
kiloTens: number,
kiloOnes: number,
kiloPower?: number,
): string,
(kiloHundreds: number, kiloTens: number, kiloOnes: number, kiloPower?: number): string
}

const combiningPrefix: CombiningPrefix = (
kiloHundredsRaw,
kiloTens,
kiloOnes,
kiloPower = 0,
) => {
const combiningPrefix: CombiningPrefix = (kiloHundredsRaw, kiloTens, kiloOnes, kiloPower = 0) => {
let kiloHundreds = kiloHundredsRaw
let prefix = ''

@@ -25,8 +15,8 @@ const combiningPrefix: CombiningPrefix = (
if (isMillia) {
prefix += combiningPrefix(
Math.floor(kiloHundredsRaw / 1000),
Math.floor(kiloHundredsRaw / 100 % 10),
Math.floor(kiloHundredsRaw / 10 % 10),
Math.floor((kiloHundredsRaw / 100) % 10),
Math.floor((kiloHundredsRaw / 10) % 10),
kiloPower + 1,
)
kiloHundreds = kiloHundredsRaw % 10
@@ -38,43 +28,18 @@ const combiningPrefix: CombiningPrefix = (
}

if (
(
kiloPower > 0
&& (
(
kiloHundreds === 0
&& kiloTens === 0
&& kiloOnes > 1
)
|| (
(
kiloHundreds > 0
|| kiloTens > 0
)
&& kiloOnes > 0
)
|| (
kiloHundreds === 0
&& kiloTens === 0
&& kiloOnes === 1
&& prefix.endsWith(NAMES.kiloThousand)
)
)
)
kiloPower > 0 &&
((kiloHundreds === 0 && kiloTens === 0 && kiloOnes > 1) ||
((kiloHundreds > 0 || kiloTens > 0) && kiloOnes > 0) ||
(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 1 && prefix.endsWith(NAMES.kiloThousand)))
) {
// http://www.isthe.com/chongo/tech/math/number/howhigh.html
// Section: Titanic size numbers < 10^3000003
prefix += ones(
kiloOnes,
false
)
prefix += ones(kiloOnes, false)
}
if (kiloPower === 0 && kiloOnes > 0) {
const special = kiloHundreds === 0 && kiloTens === 0
prefix += ones(
kiloOnes,
special
)
prefix += ones(kiloOnes, special)
if (special && [5, 6].includes(kiloOnes)) {
prefix += 't'
}
@@ -84,11 +49,7 @@ const combiningPrefix: CombiningPrefix = (
}

if (kiloPower > 0) {
if (!(
kiloHundreds === 0
&& kiloTens === 0
&& kiloOnes === 0
)) {
if (!(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 0)) {
for (let p = 0; p < kiloPower; p += 1) {
prefix += NAMES.kiloThousand
}
@@ -96,11 +57,7 @@ const combiningPrefix: CombiningPrefix = (
return prefix
}

if (
(kiloHundreds === 0 && kiloTens > 1)
|| (kiloHundreds > 0 && kiloTens !== 1)
|| kiloHundredsRaw >= 10
) {
if ((kiloHundreds === 0 && kiloTens > 1) || (kiloHundreds > 0 && kiloTens !== 1) || kiloHundredsRaw >= 10) {
prefix += 't'
}
return prefix + 'i'


+ 1
- 1
src/systems/de/base/kilo/hundreds.test.ts View File

@@ -23,6 +23,6 @@ test.each`
${7} | ${'700'} | ${'septingen'}
${8} | ${'800'} | ${'octingen'}
${9} | ${'900'} | ${'nongen'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(hundreds(value)).toBe(name)
})

+ 1
- 1
src/systems/de/base/kilo/hundreds.ts View File

@@ -1,7 +1,7 @@
import NAMES from '../../names.json'

interface Hundreds {
(kiloHundreds: number): string,
(kiloHundreds: number): string
}

const hundreds: Hundreds = (kiloHundreds) => NAMES.kiloHundreds[kiloHundreds]


+ 2
- 2
src/systems/de/base/kilo/ones.test.ts View File

@@ -25,7 +25,7 @@ describe('on ordinary units', () => {
${7} | ${'7'} | ${'septen'}
${8} | ${'8'} | ${'octo'}
${9} | ${'9'} | ${'novem'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(ones(value, false)).toBe(name)
})
})
@@ -43,7 +43,7 @@ describe('on special units', () => {
${7} | ${'7'} | ${'sept'}
${8} | ${'8'} | ${'oct'}
${9} | ${'9'} | ${'non'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(ones(value, true)).toBe(name)
})
})

+ 3
- 6
src/systems/de/base/kilo/ones.ts View File

@@ -1,13 +1,10 @@
import NAMES from '../../names.json'

interface Ones {
(kiloOnes: number, special: boolean): string,
(kiloOnes: number, special: boolean): string
}

const ones: Ones = (kiloOnes, special = false) => (
special
? NAMES.kiloSpecialUnits[kiloOnes]
: NAMES.kiloUnits[kiloOnes]
)
const ones: Ones = (kiloOnes, special = false) =>
special ? NAMES.kiloSpecialUnits[kiloOnes] : NAMES.kiloUnits[kiloOnes]

export default ones

+ 1
- 1
src/systems/de/base/kilo/tens.test.ts View File

@@ -23,6 +23,6 @@ test.each`
${7} | ${'70'} | ${'septuagin'}
${8} | ${'80'} | ${'octogin'}
${9} | ${'90'} | ${'nonagin'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(tens(value)).toBe(name)
})

+ 1
- 1
src/systems/de/base/kilo/tens.ts View File

@@ -1,7 +1,7 @@
import NAMES from '../../names.json'

interface Tens {
(kiloTens: number): string,
(kiloTens: number): string
}

const tens: Tens = (kiloTens) => NAMES.kiloTens[kiloTens]


+ 1
- 2
src/systems/de/base/ones.test.ts View File

@@ -24,7 +24,6 @@ test.each`
${7} | ${'7'} | ${'sieben'}
${8} | ${'8'} | ${'acht'}
${9} | ${'9'} | ${'neun'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(ones(value)).toBe(name)
})


+ 1
- 1
src/systems/de/base/tenPlus.test.ts View File

@@ -24,6 +24,6 @@ test.each`
${7} | ${'17'} | ${'siebzehn'}
${8} | ${'18'} | ${'achtzehn'}
${9} | ${'19'} | ${'neunzehn'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(tenPlus(value)).toBe(name)
})

+ 1
- 1
src/systems/de/base/tenTimes.test.ts View File

@@ -23,6 +23,6 @@ test.each`
${7} | ${'70'} | ${'siebzig'}
${8} | ${'80'} | ${'achtzig'}
${9} | ${'90'} | ${'neunzig'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(tenTimes(value)).toBe(name)
})

+ 24
- 24
src/systems/de/construct/tens.test.ts View File

@@ -25,7 +25,7 @@ describe('on 0 in tens place', () => {
${7} | ${'sieben'}
${8} | ${'acht'}
${9} | ${'neun'}
`(`should return "$onesName" for $ones`, ({ ones, onesName, }) => {
`(`should return "$onesName" for $ones`, ({ ones, onesName }) => {
expect(tensFn(0, ones)).toBe(onesName)
})
})
@@ -43,35 +43,35 @@ describe('on 1 in tens place', () => {
${7} | ${'siebzehn'}
${8} | ${'achtzehn'}
${9} | ${'neunzehn'}
`(`should return "$tenPlusName" for 1$ones`, ({ ones, tenPlusName, }) => {
`(`should return "$tenPlusName" for 1$ones`, ({ ones, tenPlusName }) => {
expect(tensFn(1, ones)).toBe(tenPlusName)
})
})

describe.each`
tens | tensName
${2} | ${'zwanzig'}
${3} | ${'dreißig'}
${4} | ${'vierzig'}
${5} | ${'fünfzig'}
${6} | ${'sechzig'}
${7} | ${'siebzig'}
${8} | ${'achtzig'}
${9} | ${'neunzig'}
`('on $tens in tens place', ({ tens, tensName, }) => {
tens | tensName
${2} | ${'zwanzig'}
${3} | ${'dreißig'}
${4} | ${'vierzig'}
${5} | ${'fünfzig'}
${6} | ${'sechzig'}
${7} | ${'siebzig'}
${8} | ${'achtzig'}
${9} | ${'neunzig'}
`('on $tens in tens place', ({ tens, tensName }) => {
test.each`
ones | display
${0} | ${'' + tensName}
${1} | ${'einund' + tensName}
${2} | ${'zweiund' + tensName}
${3} | ${'dreiund' + tensName}
${4} | ${'vierund' + tensName}
${5} | ${'fünfund' + tensName}
${6} | ${'sechsund' + tensName}
${7} | ${'siebenund' + tensName}
${8} | ${'achtund' + tensName}
${9} | ${'neunund' + tensName}
`(`should return "$display" for ${tens}$ones`, ({ ones, display, }) => {
ones | display
${0} | ${'' + tensName}
${1} | ${'einund' + tensName}
${2} | ${'zweiund' + tensName}
${3} | ${'dreiund' + tensName}
${4} | ${'vierund' + tensName}
${5} | ${'fünfund' + tensName}
${6} | ${'sechsund' + tensName}
${7} | ${'siebenund' + tensName}
${8} | ${'achtund' + tensName}
${9} | ${'neunund' + tensName}
`(`should return "$display" for ${tens}$ones`, ({ ones, display }) => {
expect(tensFn(tens, ones)).toBe(display)
})
})

+ 2
- 11
src/systems/de/construct/tens.ts View File

@@ -4,7 +4,7 @@ import tenPlus from '../base/tenPlus'
import getBaseTenTimesName from '../base/tenTimes'

interface Tens {
(x10: number, x1: number): string,
(x10: number, x1: number): string
}

const tens: Tens = (x10, x1) => {
@@ -20,16 +20,7 @@ const tens: Tens = (x10, x1) => {
break
}

return (
x1 > 0
? [
ones(x1),
NAMES.and,
getBaseTenTimesName(x10),
]
.join('')
: getBaseTenTimesName(x10)
)
return x1 > 0 ? [ones(x1), NAMES.and, getBaseTenTimesName(x10)].join('') : getBaseTenTimesName(x10)
}

export default tens

+ 7
- 7
src/systems/de/getLongKiloName.test.ts View File

@@ -34,7 +34,7 @@ test.each`
${17} | ${'Octilliard'}
${18} | ${'Nonillion'}
${19} | ${'Nonilliard'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -49,7 +49,7 @@ test.each`
${140} | ${'Septuagintillion'}
${160} | ${'Octogintillion'}
${180} | ${'Nonagintillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -64,7 +64,7 @@ test.each`
${1400} | ${'Septingentillion'}
${1600} | ${'Octingentillion'}
${1800} | ${'Nongentillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -79,7 +79,7 @@ test.each`
${14000} | ${'Septenmilliatillion'}
${16000} | ${'Octomilliatillion'}
${18000} | ${'Novemmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -94,7 +94,7 @@ test.each`
${140000} | ${'Septuaginmilliatillion'}
${160000} | ${'Octoginmilliatillion'}
${180000} | ${'Nonaginmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -109,7 +109,7 @@ test.each`
${1400000} | ${'Septingenmilliatillion'}
${1600000} | ${'Octingenmilliatillion'}
${1800000} | ${'Nongenmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -124,6 +124,6 @@ test.each`
${14000000} | ${'Septenmilliamilliatillion'}
${16000000} | ${'Octomilliamilliatillion'}
${18000000} | ${'Novemmilliamilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

+ 7
- 15
src/systems/de/getLongKiloName.ts View File

@@ -1,12 +1,10 @@
import { GetKiloName, } from '../../common/NumberSystem'
import { GetKiloName } from '../../NumberSystem'
import NAMES from './names.json'
import getKiloCombiningPrefix from './base/kilo/combiningPrefix'

const capitalizeFirstLetter = (word: string) => (
word.slice(0, 1).toUpperCase() + word.slice(1)
)
const capitalizeFirstLetter = (word: string) => word.slice(0, 1).toUpperCase() + word.slice(1)

const getLongKiloName: GetKiloName = thousandPower => {
const getLongKiloName: GetKiloName = (thousandPower) => {
if (thousandPower === 0) {
return ''
}
@@ -15,18 +13,12 @@ const getLongKiloName: GetKiloName = thousandPower => {
}
const kilo = thousandPower
const kiloHundreds = Math.floor(kilo / 2 / 100)
const kiloTens = Math.floor(kilo / 2 / 10 % 10)
const kiloOnes = Math.floor(kilo / 2 % 10)
const kiloCombiningPrefix = getKiloCombiningPrefix(
kiloHundreds,
kiloTens,
kiloOnes
)
const kiloTens = Math.floor((kilo / 2 / 10) % 10)
const kiloOnes = Math.floor((kilo / 2) % 10)
const kiloCombiningPrefix = getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes)

return capitalizeFirstLetter(
thousandPower % 2 === 0
? kiloCombiningPrefix + NAMES.kiloEvenSuffix
: kiloCombiningPrefix + NAMES.kiloOddSuffix
thousandPower % 2 === 0 ? kiloCombiningPrefix + NAMES.kiloEvenSuffix : kiloCombiningPrefix + NAMES.kiloOddSuffix,
)
}



+ 2
- 2
src/systems/en.ts View File

@@ -1,4 +1,4 @@
import NumberSystem from '../common/NumberSystem'
import NumberSystem from '../NumberSystem'
import getKiloCount from './en/getKiloCount'
import getLongKiloName from './en/getLongKiloName'
import getShortKiloName from './en/getShortKiloName'
@@ -8,7 +8,7 @@ const en: NumberSystem = {
getKiloName: {
short: getShortKiloName,
long: getLongKiloName,
}
},
}

export default en

+ 1
- 1
src/systems/en/base/hundredTimes.test.ts View File

@@ -23,6 +23,6 @@ test.each`
${7} | ${'700'} | ${'seven hundred'}
${8} | ${'800'} | ${'eight hundred'}
${9} | ${'900'} | ${'nine hundred'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(hundredTimes(value)).toBe(name)
})

+ 2
- 8
src/systems/en/base/hundredTimes.ts View File

@@ -9,13 +9,7 @@ interface HundredTimes {
* @param {number} x100 - The number in the hundreds place.
* @returns {string} The name of the number in the hundreds place.
*/
const hundredTimes: HundredTimes = (x100) => (
x100 === 0
? NAMES.units[0]
: [
NAMES.units[x100],
NAMES.hundred,
].join(' ')
)
const hundredTimes: HundredTimes = (x100) =>
x100 === 0 ? NAMES.units[0] : [NAMES.units[x100], NAMES.hundred].join(' ')

export default hundredTimes

+ 13
- 22
src/systems/en/base/kilo/combiningPrefix.test.ts View File

@@ -25,7 +25,7 @@ describe('on 0 in hundreds place', () => {
${7} | ${'7'} | ${'septi'}
${8} | ${'8'} | ${'octi'}
${9} | ${'9'} | ${'noni'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(0, 0, value)).toBe(name)
})
})
@@ -41,7 +41,7 @@ describe('on 0 in hundreds place', () => {
${7} | ${'septuaginti'}
${8} | ${'octoginti'}
${9} | ${'nonaginti'}
`('on $tens in tens place', ({ tens, tensName, }) => {
`('on $tens in tens place', ({ tens, tensName }) => {
test.each`
ones | display
${0} | ${tensName}
@@ -54,7 +54,7 @@ describe('on 0 in hundreds place', () => {
${7} | ${'septen' + tensName}
${8} | ${'octo' + tensName}
${9} | ${'novem' + tensName}
`(`should return "$display" for ${tens}$ones`, ({ ones, display, }) => {
`(`should return "$display" for ${tens}$ones`, ({ ones, display }) => {
expect(combiningPrefix(0, tens, ones)).toBe(display)
})
})
@@ -71,7 +71,7 @@ describe.each`
${7} | ${'septingen'}
${8} | ${'octingen'}
${9} | ${'nongen'}
`('on $hundreds in hundreds place', ({ hundreds, hundredsName, }) => {
`('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => {
describe.each`
tens | tensName
${0} | ${'ti'}
@@ -84,7 +84,7 @@ describe.each`
${7} | ${'septuaginti'}
${8} | ${'octoginti'}
${9} | ${'nonaginti'}
`('on $tens in tens place', ({ tens, tensName, }) => {
`('on $tens in tens place', ({ tens, tensName }) => {
test.each`
ones | display
${0} | ${hundredsName + tensName}
@@ -97,7 +97,7 @@ describe.each`
${7} | ${hundredsName + 'septen' + tensName}
${8} | ${hundredsName + 'octo' + tensName}
${9} | ${hundredsName + 'novem' + tensName}
`(`should return "$display" for ${hundreds}${tens}$ones`, ({ ones, display, }) => {
`(`should return "$display" for ${hundreds}${tens}$ones`, ({ ones, display }) => {
expect(combiningPrefix(hundreds, tens, ones)).toBe(display)
})
})
@@ -114,7 +114,7 @@ describe.each`
${7} | ${'septingen'}
${8} | ${'octingen'}
${9} | ${'nongen'}
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName, }) => {
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName }) => {
describe.each`
tenThousands | tenThousandsName
${0} | ${''}
@@ -127,7 +127,7 @@ describe.each`
${7} | ${'septuagin'}
${8} | ${'octogin'}
${9} | ${'nonagin'}
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName, }) => {
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName }) => {
test.each`
thousands | display | name
${0} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milliati'}
@@ -140,17 +140,9 @@ describe.each`
${7000} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milliati'}
${8000} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'octo' + tenThousandsName + 'milliati'}
${9000} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'novem' + tenThousandsName + 'milliati'}
`(`should return "$name" for $display`, ({ thousands, name, }) => {
const kiloHundreds = (
hundredThousands * 1000
+ tenThousands * 100
+ thousands / 100
)
expect(combiningPrefix(
kiloHundreds,
0,
0,
)).toBe(name)
`(`should return "$name" for $display`, ({ thousands, name }) => {
const kiloHundreds = hundredThousands * 1000 + tenThousands * 100 + thousands / 100
expect(combiningPrefix(kiloHundreds, 0, 0)).toBe(name)
})
})
})
@@ -166,7 +158,7 @@ test.each`
${7} | ${'7000000'} | ${'septenmilliamilliati'}
${8} | ${'8000000'} | ${'octomilliamilliati'}
${9} | ${'9000000'} | ${'novemmilliamilliati'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(value * 10000, 0, 0)).toBe(name)
})

@@ -181,7 +173,6 @@ test.each`
${7} | ${'7007000'} | ${'septenmilliamilliaseptenmilliati'}
${8} | ${'8008000'} | ${'octomilliamilliaoctomilliati'}
${9} | ${'9009000'} | ${'novemmilliamillianovemmilliati'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(value * 10010, 0, 0)).toBe(name)
})


+ 12
- 55
src/systems/en/base/kilo/combiningPrefix.ts View File

@@ -4,20 +4,10 @@ import tens from './tens'
import hundreds from './hundreds'

interface CombiningPrefix {
(
kiloHundreds: number,
kiloTens: number,
kiloOnes: number,
kiloPower?: number,
): string,
(kiloHundreds: number, kiloTens: number, kiloOnes: number, kiloPower?: number): string
}

const combiningPrefix: CombiningPrefix = (
kiloHundredsRaw,
kiloTens,
kiloOnes,
kiloPower = 0,
) => {
const combiningPrefix: CombiningPrefix = (kiloHundredsRaw, kiloTens, kiloOnes, kiloPower = 0) => {
let kiloHundreds = kiloHundredsRaw
let prefix = ''

@@ -25,8 +15,8 @@ const combiningPrefix: CombiningPrefix = (
if (isMillia) {
prefix += combiningPrefix(
Math.floor(kiloHundredsRaw / 1000),
Math.floor(kiloHundredsRaw / 100 % 10),
Math.floor(kiloHundredsRaw / 10 % 10),
Math.floor((kiloHundredsRaw / 100) % 10),
Math.floor((kiloHundredsRaw / 10) % 10),
kiloPower + 1,
)
kiloHundreds = kiloHundredsRaw % 10
@@ -38,43 +28,18 @@ const combiningPrefix: CombiningPrefix = (
}

if (
(
kiloPower > 0
&& (
(
kiloHundreds === 0
&& kiloTens === 0
&& kiloOnes > 1
)
|| (
(
kiloHundreds > 0
|| kiloTens > 0
)
&& kiloOnes > 0
)
|| (
kiloHundreds === 0
&& kiloTens === 0
&& kiloOnes === 1
&& prefix.endsWith(NAMES.kiloThousand)
)
)
)
kiloPower > 0 &&
((kiloHundreds === 0 && kiloTens === 0 && kiloOnes > 1) ||
((kiloHundreds > 0 || kiloTens > 0) && kiloOnes > 0) ||
(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 1 && prefix.endsWith(NAMES.kiloThousand)))
) {
// http://www.isthe.com/chongo/tech/math/number/howhigh.html
// Section: Titanic size numbers < 10^3000003
prefix += ones(
kiloOnes,
false
)
prefix += ones(kiloOnes, false)
}
if (kiloPower === 0 && kiloOnes > 0) {
const special = kiloHundreds === 0 && kiloTens === 0
prefix += ones(
kiloOnes,
special
)
prefix += ones(kiloOnes, special)
if (special && [5, 6].includes(kiloOnes)) {
prefix += 't'
}
@@ -84,11 +49,7 @@ const combiningPrefix: CombiningPrefix = (
}

if (kiloPower > 0) {
if (!(
kiloHundreds === 0
&& kiloTens === 0
&& kiloOnes === 0
)) {
if (!(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 0)) {
for (let p = 0; p < kiloPower; p += 1) {
prefix += NAMES.kiloThousand
}
@@ -96,11 +57,7 @@ const combiningPrefix: CombiningPrefix = (
return prefix
}

if (
(kiloHundreds === 0 && kiloTens > 1)
|| (kiloHundreds > 0 && kiloTens !== 1)
|| kiloHundredsRaw >= 10
) {
if ((kiloHundreds === 0 && kiloTens > 1) || (kiloHundreds > 0 && kiloTens !== 1) || kiloHundredsRaw >= 10) {
prefix += 't'
}
return prefix + 'i'


+ 1
- 1
src/systems/en/base/kilo/hundreds.test.ts View File

@@ -23,6 +23,6 @@ test.each`
${7} | ${'700'} | ${'septingen'}
${8} | ${'800'} | ${'octingen'}
${9} | ${'900'} | ${'nongen'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(hundreds(value)).toBe(name)
})

+ 1
- 1
src/systems/en/base/kilo/hundreds.ts View File

@@ -1,7 +1,7 @@
import NAMES from '../../names.json'

interface Hundreds {
(kiloHundreds: number): string,
(kiloHundreds: number): string
}

const hundreds: Hundreds = (kiloHundreds) => NAMES.kiloHundreds[kiloHundreds]


+ 2
- 2
src/systems/en/base/kilo/ones.test.ts View File

@@ -25,7 +25,7 @@ describe('on ordinary units', () => {
${7} | ${'7'} | ${'septen'}
${8} | ${'8'} | ${'octo'}
${9} | ${'9'} | ${'novem'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(ones(value, false)).toBe(name)
})
})
@@ -43,7 +43,7 @@ describe('on special units', () => {
${7} | ${'7'} | ${'sept'}
${8} | ${'8'} | ${'oct'}
${9} | ${'9'} | ${'non'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(ones(value, true)).toBe(name)
})
})

+ 3
- 6
src/systems/en/base/kilo/ones.ts View File

@@ -1,13 +1,10 @@
import NAMES from '../../names.json'

interface Ones {
(kiloOnes: number, special: boolean): string,
(kiloOnes: number, special: boolean): string
}

const ones: Ones = (kiloOnes, special = false) => (
special
? NAMES.kiloSpecialUnits[kiloOnes]
: NAMES.kiloUnits[kiloOnes]
)
const ones: Ones = (kiloOnes, special = false) =>
special ? NAMES.kiloSpecialUnits[kiloOnes] : NAMES.kiloUnits[kiloOnes]

export default ones

+ 1
- 1
src/systems/en/base/kilo/tens.test.ts View File

@@ -23,6 +23,6 @@ test.each`
${7} | ${'70'} | ${'septuagin'}
${8} | ${'80'} | ${'octogin'}
${9} | ${'90'} | ${'nonagin'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(tens(value)).toBe(name)
})

+ 1
- 1
src/systems/en/base/kilo/tens.ts View File

@@ -1,7 +1,7 @@
import NAMES from '../../names.json'

interface Tens {
(kiloTens: number): string,
(kiloTens: number): string
}

const tens: Tens = (kiloTens) => NAMES.kiloTens[kiloTens]


+ 1
- 2
src/systems/en/base/ones.test.ts View File

@@ -24,7 +24,6 @@ test.each`
${7} | ${'7'} | ${'seven'}
${8} | ${'8'} | ${'eight'}
${9} | ${'9'} | ${'nine'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(ones(value)).toBe(name)
})


+ 1
- 1
src/systems/en/base/tenPlus.test.ts View File

@@ -24,6 +24,6 @@ test.each`
${7} | ${'17'} | ${'seventeen'}
${8} | ${'18'} | ${'eighteen'}
${9} | ${'19'} | ${'nineteen'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(tenPlus(value)).toBe(name)
})

+ 1
- 1
src/systems/en/base/tenTimes.test.ts View File

@@ -23,6 +23,6 @@ test.each`
${7} | ${'70'} | ${'seventy'}
${8} | ${'80'} | ${'eighty'}
${9} | ${'90'} | ${'ninety'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(tenTimes(value)).toBe(name)
})

+ 25
- 28
src/systems/en/construct/tens.test.ts View File

@@ -25,7 +25,7 @@ describe('on 0 in tens place', () => {
${7} | ${'seven'}
${8} | ${'eight'}
${9} | ${'nine'}
`(`should return "$onesName" for $ones`, ({ ones, onesName, }) => {
`(`should return "$onesName" for $ones`, ({ ones, onesName }) => {
expect(tensFn(0, ones)).toBe(onesName)
})
})
@@ -43,38 +43,35 @@ describe('on 1 in tens place', () => {
${7} | ${'seventeen'}
${8} | ${'eighteen'}
${9} | ${'nineteen'}
`(`should return "$tenPlusName" for 1$ones`, ({ ones, tenPlusName, }) => {
`(`should return "$tenPlusName" for 1$ones`, ({ ones, tenPlusName }) => {
expect(tensFn(1, ones)).toBe(tenPlusName)
})
})

describe.each`
tens | tensName
${2} | ${'twenty'}
${3} | ${'thirty'}
${4} | ${'forty'}
${5} | ${'fifty'}
${6} | ${'sixty'}
${7} | ${'seventy'}
${8} | ${'eighty'}
${9} | ${'ninety'}
`('on $tens in tens place', ({ tens, tensName, }) => {
tens | tensName
${2} | ${'twenty'}
${3} | ${'thirty'}
${4} | ${'forty'}
${5} | ${'fifty'}
${6} | ${'sixty'}
${7} | ${'seventy'}
${8} | ${'eighty'}
${9} | ${'ninety'}
`('on $tens in tens place', ({ tens, tensName }) => {
test.each`
ones | onesName
${0} | ${''}
${1} | ${' one'}
${2} | ${' two'}
${3} | ${' three'}
${4} | ${' four'}
${5} | ${' five'}
${6} | ${' six'}
${7} | ${' seven'}
${8} | ${' eight'}
${9} | ${' nine'}
`(`should return "${tensName}$onesName" for ${tens}$ones`, ({ ones, onesName, }) => {
expect(tensFn(tens, ones)).toBe([
tensName,
onesName
].join(''))
ones | onesName
${0} | ${''}
${1} | ${' one'}
${2} | ${' two'}
${3} | ${' three'}
${4} | ${' four'}
${5} | ${' five'}
${6} | ${' six'}
${7} | ${' seven'}
${8} | ${' eight'}
${9} | ${' nine'}
`(`should return "${tensName}$onesName" for ${tens}$ones`, ({ ones, onesName }) => {
expect(tensFn(tens, ones)).toBe([tensName, onesName].join(''))
})
})

+ 2
- 10
src/systems/en/construct/tens.ts View File

@@ -3,7 +3,7 @@ import tenPlus from '../base/tenPlus'
import getBaseTenTimesName from '../base/tenTimes'

interface Tens {
(x10: number, x1: number): string,
(x10: number, x1: number): string
}

const tens: Tens = (x10, x1) => {
@@ -19,15 +19,7 @@ const tens: Tens = (x10, x1) => {
break
}

return (
x1 > 0
? [
getBaseTenTimesName(x10),
ones(x1),
]
.join(' ')
: getBaseTenTimesName(x10)
)
return x1 > 0 ? [getBaseTenTimesName(x10), ones(x1)].join(' ') : getBaseTenTimesName(x10)
}

export default tens

+ 10
- 20
src/systems/en/getKiloCount.test.ts View File

@@ -23,7 +23,7 @@ describe.each`
${7} | ${'seven hundred'}
${8} | ${'eight hundred'}
${9} | ${'nine hundred'}
`('on $hundreds in hundreds place', ({ hundreds, hundredsName, }) => {
`('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => {
describe('on 0 in tens place', () => {
test.each`
ones | onesName
@@ -37,13 +37,10 @@ describe.each`
${7} | ${' seven'}
${8} | ${' eight'}
${9} | ${' nine'}
`(`should return "${hundredsName}$onesName" for ${hundreds}0$ones`, ({ ones, onesName, }) => {
expect(getKiloCount(hundreds, 0, ones)).toBe([
hundredsName,
onesName
].join(''))
})
`(`should return "${hundredsName}$onesName" for ${hundreds}0$ones`, ({ ones, onesName }) => {
expect(getKiloCount(hundreds, 0, ones)).toBe([hundredsName, onesName].join(''))
})
})

describe('on 1 in tens place', () => {
test.each`
@@ -58,13 +55,10 @@ describe.each`
${7} | ${' seventeen'}
${8} | ${' eighteen'}
${9} | ${' nineteen'}
`(`should return "${hundredsName}$tenPlusName" for ${hundreds}1$ones`, ({ ones, tenPlusName, }) => {
expect(getKiloCount(hundreds, 1, ones)).toBe([
hundredsName,
tenPlusName
].join(''))
})
`(`should return "${hundredsName}$tenPlusName" for ${hundreds}1$ones`, ({ ones, tenPlusName }) => {
expect(getKiloCount(hundreds, 1, ones)).toBe([hundredsName, tenPlusName].join(''))
})
})

describe.each`
tens | tensName
@@ -76,7 +70,7 @@ describe.each`
${7} | ${' seventy'}
${8} | ${' eighty'}
${9} | ${' ninety'}
`('on $tens in tens place', ({ tens, tensName, }) => {
`('on $tens in tens place', ({ tens, tensName }) => {
test.each`
ones | onesName
${0} | ${''}
@@ -89,12 +83,8 @@ describe.each`
${7} | ${' seven'}
${8} | ${' eight'}
${9} | ${' nine'}
`(`should return "${hundredsName}${tensName}$onesName" for ${hundreds}${tens}$ones`, ({ ones, onesName, }) => {
expect(getKiloCount(hundreds, tens, ones)).toBe([
hundredsName,
tensName,
onesName
].join(''))
`(`should return "${hundredsName}${tensName}$onesName" for ${hundreds}${tens}$ones`, ({ ones, onesName }) => {
expect(getKiloCount(hundreds, tens, ones)).toBe([hundredsName, tensName, onesName].join(''))
})
})
})

+ 3
- 11
src/systems/en/getKiloCount.ts View File

@@ -1,12 +1,8 @@
import { GetKiloCount, } from '../../common/NumberSystem'
import { GetKiloCount } from '../../NumberSystem'
import constructTens from './construct/tens'
import hundredTimes from './base/hundredTimes'

const getKiloCount: GetKiloCount = (
x100,
x10,
x1
) => {
const getKiloCount: GetKiloCount = (x100, x10, x1) => {
if (x100 < 1) {
return constructTens(x10, x1)
}
@@ -14,11 +10,7 @@ const getKiloCount: GetKiloCount = (
if (x10 === 0 && x1 === 0) {
return hundredTimes(x100)
}
return [
hundredTimes(x100),
constructTens(x10, x1),
]
.join(' ')
return [hundredTimes(x100), constructTens(x10, x1)].join(' ')
}

export default getKiloCount

+ 7
- 7
src/systems/en/getLongKiloName.test.ts View File

@@ -34,7 +34,7 @@ test.each`
${17} | ${'thousand octillion'}
${18} | ${'nonillion'}
${19} | ${'thousand nonillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -49,7 +49,7 @@ test.each`
${140} | ${'septuagintillion'}
${160} | ${'octogintillion'}
${180} | ${'nonagintillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -64,7 +64,7 @@ test.each`
${1400} | ${'septingentillion'}
${1600} | ${'octingentillion'}
${1800} | ${'nongentillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -79,7 +79,7 @@ test.each`
${14000} | ${'septenmilliatillion'}
${16000} | ${'octomilliatillion'}
${18000} | ${'novemmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -94,7 +94,7 @@ test.each`
${140000} | ${'septuaginmilliatillion'}
${160000} | ${'octoginmilliatillion'}
${180000} | ${'nonaginmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -109,7 +109,7 @@ test.each`
${1400000} | ${'septingenmilliatillion'}
${1600000} | ${'octingenmilliatillion'}
${1800000} | ${'nongenmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -124,6 +124,6 @@ test.each`
${14000000} | ${'septenmilliamilliatillion'}
${16000000} | ${'octomilliamilliatillion'}
${18000000} | ${'novemmilliamilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

+ 6
- 14
src/systems/en/getLongKiloName.ts View File

@@ -1,8 +1,8 @@
import { GetKiloName, } from '../../common/NumberSystem'
import { GetKiloName } from '../../NumberSystem'
import NAMES from './names.json'
import getKiloCombiningPrefix from './base/kilo/combiningPrefix'

const getLongKiloName: GetKiloName = thousandPower => {
const getLongKiloName: GetKiloName = (thousandPower) => {
if (thousandPower === 0) {
return ''
}
@@ -11,19 +11,11 @@ const getLongKiloName: GetKiloName = thousandPower => {
}
const kilo = thousandPower
const kiloHundreds = Math.floor(kilo / 2 / 100)
const kiloTens = Math.floor(kilo / 2 / 10 % 10)
const kiloOnes = Math.floor(kilo / 2 % 10)
const baseKiloName = getKiloCombiningPrefix(
kiloHundreds,
kiloTens,
kiloOnes
) + NAMES.kiloEvenSuffix
const kiloTens = Math.floor((kilo / 2 / 10) % 10)
const kiloOnes = Math.floor((kilo / 2) % 10)
const baseKiloName = getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes) + NAMES.kiloEvenSuffix

return (
thousandPower % 2 === 0
? baseKiloName
: NAMES.thousand + ' ' + baseKiloName
)
return thousandPower % 2 === 0 ? baseKiloName : NAMES.thousand + ' ' + baseKiloName
}

export default getLongKiloName

+ 7
- 7
src/systems/en/getShortKiloName.test.ts View File

@@ -25,7 +25,7 @@ test.each`
${8} | ${'septillion'}
${9} | ${'octillion'}
${10} | ${'nonillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -40,7 +40,7 @@ test.each`
${71} | ${'septuagintillion'}
${81} | ${'octogintillion'}
${91} | ${'nonagintillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -55,7 +55,7 @@ test.each`
${701} | ${'septingentillion'}
${801} | ${'octingentillion'}
${901} | ${'nongentillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -70,7 +70,7 @@ test.each`
${7001} | ${'septenmilliatillion'}
${8001} | ${'octomilliatillion'}
${9001} | ${'novemmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -85,7 +85,7 @@ test.each`
${70001} | ${'septuaginmilliatillion'}
${80001} | ${'octoginmilliatillion'}
${90001} | ${'nonaginmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -100,7 +100,7 @@ test.each`
${700001} | ${'septingenmilliatillion'}
${800001} | ${'octingenmilliatillion'}
${900001} | ${'nongenmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

@@ -115,6 +115,6 @@ test.each`
${7000001} | ${'septenmilliamilliatillion'}
${8000001} | ${'octomilliamilliatillion'}
${9000001} | ${'novemmilliamilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower, }) => {
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

+ 4
- 8
src/systems/en/getShortKiloName.ts View File

@@ -1,8 +1,8 @@
import { GetKiloName, } from '../../common/NumberSystem'
import { GetKiloName } from '../../NumberSystem'
import NAMES from './names.json'
import getKiloCombiningPrefix from './base/kilo/combiningPrefix'

const getKiloName: GetKiloName = thousandPower => {
const getKiloName: GetKiloName = (thousandPower) => {
if (thousandPower === 0) {
return ''
}
@@ -11,14 +11,10 @@ const getKiloName: GetKiloName = thousandPower => {
}
const kilo = thousandPower - 1
const kiloHundreds = Math.floor(kilo / 100)
const kiloTens = Math.floor(kilo / 10 % 10)
const kiloTens = Math.floor((kilo / 10) % 10)
const kiloOnes = Math.floor(kilo % 10)

return getKiloCombiningPrefix(
kiloHundreds,
kiloTens,
kiloOnes
) + NAMES.kiloEvenSuffix
return getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes) + NAMES.kiloEvenSuffix
}

export default getKiloName

+ 1
- 1
src/systems/tl/base/hundredTimes.test.ts View File

@@ -23,6 +23,6 @@ test.each`
${7} | ${'700'} | ${'pitongdaan'}
${8} | ${'800'} | ${'walongdaan'}
${9} | ${'900'} | ${'siyamnaraan'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(hundredTimes(value)).toBe(name)
})

+ 1
- 6
src/systems/tl/base/hundredTimes.ts View File

@@ -48,12 +48,7 @@ const hundredTimes: HundredTimes = (x100) => {
break
}

return [
hundredFactorCombining,
infix,
hundredSuffixCombining,
]
.join('')
return [hundredFactorCombining, infix, hundredSuffixCombining].join('')
}

export default hundredTimes

+ 13
- 22
src/systems/tl/base/kilo/combiningPrefix.test.ts View File

@@ -25,7 +25,7 @@ describe('on 0 in hundreds place', () => {
${7} | ${'7'} | ${'septi'}
${8} | ${'8'} | ${'okti'}
${9} | ${'9'} | ${'noni'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(0, 0, value)).toBe(name)
})
})
@@ -41,7 +41,7 @@ describe('on 0 in hundreds place', () => {
${7} | ${'septuwahinti'}
${8} | ${'oktohinti'}
${9} | ${'nonahinti'}
`('on $tens in tens place', ({ tens, tensName, }) => {
`('on $tens in tens place', ({ tens, tensName }) => {
test.each`
ones | display
${0} | ${tensName}
@@ -54,7 +54,7 @@ describe('on 0 in hundreds place', () => {
${7} | ${'septen' + tensName}
${8} | ${'okto' + tensName}
${9} | ${'nobem' + tensName}
`(`should return "$display" for ${tens}$ones`, ({ ones, display, }) => {
`(`should return "$display" for ${tens}$ones`, ({ ones, display }) => {
expect(combiningPrefix(0, tens, ones)).toBe(display)
})
})
@@ -71,7 +71,7 @@ describe.each`
${7} | ${'septinghen'}
${8} | ${'oktinghen'}
${9} | ${'nonghen'}
`('on $hundreds in hundreds place', ({ hundreds, hundredsName, }) => {
`('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => {
describe.each`
tens | tensName
${0} | ${'ti'}
@@ -84,7 +84,7 @@ describe.each`
${7} | ${'septuwahinti'}
${8} | ${'oktohinti'}
${9} | ${'nonahinti'}
`('on $tens in tens place', ({ tens, tensName, }) => {
`('on $tens in tens place', ({ tens, tensName }) => {
test.each`
ones | display
${0} | ${hundredsName + tensName}
@@ -97,7 +97,7 @@ describe.each`
${7} | ${hundredsName + 'septen' + tensName}
${8} | ${hundredsName + 'okto' + tensName}
${9} | ${hundredsName + 'nobem' + tensName}
`(`should return "$display" for ${hundreds}${tens}$ones`, ({ ones, display, }) => {
`(`should return "$display" for ${hundreds}${tens}$ones`, ({ ones, display }) => {
expect(combiningPrefix(hundreds, tens, ones)).toBe(display)
})
})
@@ -114,7 +114,7 @@ describe.each`
${7} | ${'septinghen'}
${8} | ${'oktinghen'}
${9} | ${'nonghen'}
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName, }) => {
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName }) => {
describe.each`
tenThousands | tenThousandsName
${0} | ${''}
@@ -127,7 +127,7 @@ describe.each`
${7} | ${'septuwahin'}
${8} | ${'oktohin'}
${9} | ${'nonahin'}
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName, }) => {
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName }) => {
test.each`
thousands | display | name
${0} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milyati'}
@@ -140,17 +140,9 @@ describe.each`
${7000} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milyati'}
${8000} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'okto' + tenThousandsName + 'milyati'}
${9000} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'nobem' + tenThousandsName + 'milyati'}
`(`should return "$name" for $display`, ({ thousands, name, }) => {
const kiloHundreds = (
hundredThousands * 1000
+ tenThousands * 100
+ thousands / 100
)
expect(combiningPrefix(
kiloHundreds,
0,
0,
)).toBe(name)
`(`should return "$name" for $display`, ({ thousands, name }) => {
const kiloHundreds = hundredThousands * 1000 + tenThousands * 100 + thousands / 100
expect(combiningPrefix(kiloHundreds, 0, 0)).toBe(name)
})
})
})
@@ -166,7 +158,7 @@ it.each`
${7} | ${'7000000'} | ${'septenmilyamilyati'}
${8} | ${'8000000'} | ${'oktomilyamilyati'}
${9} | ${'9000000'} | ${'nobemmilyamilyati'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(value * 10000, 0, 0)).toBe(name)
})

@@ -181,7 +173,6 @@ it.each`
${7} | ${'7007000'} | ${'septenmilyamilyaseptenmilyati'}
${8} | ${'8008000'} | ${'oktomilyamilyaoktomilyati'}
${9} | ${'9009000'} | ${'nobemmilyamilyanobemmilyati'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(value * 10010, 0, 0)).toBe(name)
})


+ 12
- 55
src/systems/tl/base/kilo/combiningPrefix.ts View File

@@ -4,20 +4,10 @@ import tens from './tens'
import hundreds from './hundreds'

interface CombiningPrefix {
(
kiloHundreds: number,
kiloTens: number,
kiloOnes: number,
kiloPower?: number,
): string,
(kiloHundreds: number, kiloTens: number, kiloOnes: number, kiloPower?: number): string
}

const combiningPrefix: CombiningPrefix = (
kiloHundredsRaw,
kiloTens,
kiloOnes,
kiloPower = 0,
) => {
const combiningPrefix: CombiningPrefix = (kiloHundredsRaw, kiloTens, kiloOnes, kiloPower = 0) => {
let kiloHundreds = kiloHundredsRaw
let prefix = ''

@@ -25,8 +15,8 @@ const combiningPrefix: CombiningPrefix = (
if (isMillia) {
prefix += combiningPrefix(
Math.floor(kiloHundredsRaw / 1000),
Math.floor(kiloHundredsRaw / 100 % 10),
Math.floor(kiloHundredsRaw / 10 % 10),
Math.floor((kiloHundredsRaw / 100) % 10),
Math.floor((kiloHundredsRaw / 10) % 10),
kiloPower + 1,
)
kiloHundreds = kiloHundredsRaw % 10
@@ -38,43 +28,18 @@ const combiningPrefix: CombiningPrefix = (
}

if (
(
kiloPower > 0
&& (
(
kiloHundreds === 0
&& kiloTens === 0
&& kiloOnes > 1
)
|| (
(
kiloHundreds > 0
|| kiloTens > 0
)
&& kiloOnes > 0
)
|| (
kiloHundreds === 0
&& kiloTens === 0
&& kiloOnes === 1
&& prefix.endsWith(NAMES.kiloThousand)
)
)
)
kiloPower > 0 &&
((kiloHundreds === 0 && kiloTens === 0 && kiloOnes > 1) ||
((kiloHundreds > 0 || kiloTens > 0) && kiloOnes > 0) ||
(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 1 && prefix.endsWith(NAMES.kiloThousand)))
) {
// http://www.isthe.com/chongo/tech/math/number/howhigh.html
// Section: Titanic size numbers < 10^3000003
prefix += ones(
kiloOnes,
false
)
prefix += ones(kiloOnes, false)
}
if (kiloPower === 0 && kiloOnes > 0) {
const special = kiloHundreds === 0 && kiloTens === 0
prefix += ones(
kiloOnes,
special
)
prefix += ones(kiloOnes, special)
if (special && [5, 6].includes(kiloOnes)) {
prefix += 't'
}
@@ -84,11 +49,7 @@ const combiningPrefix: CombiningPrefix = (
}

if (kiloPower > 0) {
if (!(
kiloHundreds === 0
&& kiloTens === 0
&& kiloOnes === 0
)) {
if (!(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 0)) {
for (let p = 0; p < kiloPower; p += 1) {
prefix += NAMES.kiloThousand
}
@@ -96,11 +57,7 @@ const combiningPrefix: CombiningPrefix = (
return prefix
}

if (
(kiloHundreds === 0 && kiloTens > 1)
|| (kiloHundreds > 0 && kiloTens !== 1)
|| kiloHundredsRaw >= 10
) {
if ((kiloHundreds === 0 && kiloTens > 1) || (kiloHundreds > 0 && kiloTens !== 1) || kiloHundredsRaw >= 10) {
prefix += 't'
}
return prefix + 'i'


+ 1
- 1
src/systems/tl/base/kilo/hundreds.test.ts View File

@@ -23,6 +23,6 @@ test.each`
${7} | ${'700'} | ${'septinghen'}
${8} | ${'800'} | ${'oktinghen'}
${9} | ${'900'} | ${'nonghen'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(hundreds(value)).toBe(name)
})

+ 1
- 1
src/systems/tl/base/kilo/hundreds.ts View File

@@ -1,7 +1,7 @@
import NAMES from '../../names.json'

interface Hundreds {
(kiloHundreds: number): string,
(kiloHundreds: number): string
}

const hundreds: Hundreds = (kiloHundreds) => NAMES.kiloHundreds[kiloHundreds]


+ 2
- 2
src/systems/tl/base/kilo/ones.test.ts View File

@@ -25,7 +25,7 @@ describe('on ordinary units', () => {
${7} | ${'7'} | ${'septen'}
${8} | ${'8'} | ${'okto'}
${9} | ${'9'} | ${'nobem'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(ones(value, false)).toBe(name)
})
})
@@ -43,7 +43,7 @@ describe('on special units', () => {
${7} | ${'7'} | ${'sept'}
${8} | ${'8'} | ${'okt'}
${9} | ${'9'} | ${'non'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(ones(value, true)).toBe(name)
})
})

+ 3
- 6
src/systems/tl/base/kilo/ones.ts View File

@@ -1,13 +1,10 @@
import NAMES from '../../names.json'

interface Ones {
(kiloOnes: number, special: boolean): string,
(kiloOnes: number, special: boolean): string
}

const ones: Ones = (kiloOnes, special = false) => (
special
? NAMES.kiloSpecialUnits[kiloOnes]
: NAMES.kiloUnits[kiloOnes]
)
const ones: Ones = (kiloOnes, special = false) =>
special ? NAMES.kiloSpecialUnits[kiloOnes] : NAMES.kiloUnits[kiloOnes]

export default ones

+ 1
- 1
src/systems/tl/base/kilo/tens.test.ts View File

@@ -23,6 +23,6 @@ test.each`
${7} | ${'70'} | ${'septuwahin'}
${8} | ${'80'} | ${'oktohin'}
${9} | ${'90'} | ${'nonahin'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(tens(value)).toBe(name)
})

+ 1
- 1
src/systems/tl/base/kilo/tens.ts View File

@@ -1,7 +1,7 @@
import NAMES from '../../names.json'

interface Tens {
(kiloTens: number): string,
(kiloTens: number): string
}

const tens: Tens = (kiloTens) => NAMES.kiloTens[kiloTens]


+ 1
- 2
src/systems/tl/base/ones.test.ts View File

@@ -24,7 +24,6 @@ test.each`
${7} | ${'7'} | ${'pito'}
${8} | ${'8'} | ${'walo'}
${9} | ${'9'} | ${'siyam'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(ones(value)).toBe(name)
})


+ 1
- 1
src/systems/tl/base/tenPlus.test.ts View File

@@ -24,6 +24,6 @@ test.each`
${7} | ${'17'} | ${'labimpito'}
${8} | ${'18'} | ${'labingwalo'}
${9} | ${'19'} | ${'labinsiyam'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(tenPlus(value)).toBe(name)
})

+ 1
- 1
src/systems/tl/base/tenTimes.test.ts View File

@@ -23,6 +23,6 @@ test.each`
${7} | ${'70'} | ${'pitumpu'}
${8} | ${'80'} | ${'walumpu'}
${9} | ${'90'} | ${'siyamnapu'}
`('should return "$name" on $display', ({ value, name, }) => {
`('should return "$name" on $display', ({ value, name }) => {
expect(tenTimes(value)).toBe(name)
})

+ 25
- 28
src/systems/tl/construct/tens.test.ts View File

@@ -25,7 +25,7 @@ describe('on 0 in tens place', () => {
${7} | ${'pito'}
${8} | ${'walo'}
${9} | ${'siyam'}
`(`should return "$onesName" for $ones`, ({ ones, onesName, }) => {
`(`should return "$onesName" for $ones`, ({ ones, onesName }) => {
expect(tensFn(0, ones)).toBe(onesName)
})
})
@@ -43,38 +43,35 @@ describe('on 1 in tens place', () => {
${7} | ${'labimpito'}
${8} | ${'labingwalo'}
${9} | ${'labinsiyam'}
`(`should return "$tenPlusName" for 1$ones`, ({ ones, tenPlusName, }) => {
`(`should return "$tenPlusName" for 1$ones`, ({ ones, tenPlusName }) => {
expect(tensFn(1, ones)).toBe(tenPlusName)
})
})

describe.each`
tens | tensName
${2} | ${'dalawampu'}
${3} | ${'tatlumpu'}
${4} | ${'apatnapu'}
${5} | ${'limampu'}
${6} | ${'animnapu'}
${7} | ${'pitumpu'}
${8} | ${'walumpu'}
${9} | ${'siyamnapu'}
`('on $tens in tens place', ({ tens, tensName, }) => {
tens | tensName
${2} | ${'dalawampu'}
${3} | ${'tatlumpu'}
${4} | ${'apatnapu'}
${5} | ${'limampu'}
${6} | ${'animnapu'}
${7} | ${'pitumpu'}
${8} | ${'walumpu'}
${9} | ${'siyamnapu'}
`('on $tens in tens place', ({ tens, tensName }) => {
test.each`
ones | onesName
${0} | ${''}
${1} | ${'\'t isa'}
${2} | ${'\'t dalawa'}
${3} | ${'\'t tatlo'}
${4} | ${'\'t apat'}
${5} | ${'\'t lima'}
${6} | ${'\'t anim'}
${7} | ${'\'t pito'}
${8} | ${'\'t walo'}
${9} | ${'\'t siyam'}
`(`should return "${tensName}$onesName" for ${tens}$ones`, ({ ones, onesName, }) => {
expect(tensFn(tens, ones)).toBe([
tensName,
onesName
].join(''))
ones | onesName
${0} | ${''}
${1} | ${"'t isa"}
${2} | ${"'t dalawa"}
${3} | ${"'t tatlo"}
${4} | ${"'t apat"}
${5} | ${"'t lima"}
${6} | ${"'t anim"}
${7} | ${"'t pito"}
${8} | ${"'t walo"}
${9} | ${"'t siyam"}
`(`should return "${tensName}$onesName" for ${tens}$ones`, ({ ones, onesName }) => {
expect(tensFn(tens, ones)).toBe([tensName, onesName].join(''))
})
})

+ 2
- 13
src/systems/tl/construct/tens.ts View File

@@ -4,7 +4,7 @@ import tenPlus from '../base/tenPlus'
import getBaseTenTimesName from '../base/tenTimes'

interface Tens {
(x10: number, x1: number): string,
(x10: number, x1: number): string
}

const tens: Tens = (x10, x1) => {
@@ -20,18 +20,7 @@ const tens: Tens = (x10, x1) => {
break
}

return (
x1 > 0
? [
getBaseTenTimesName(x10),
"'",
NAMES.and.slice(1),
' ',
ones(x1),
]
.join('')
: getBaseTenTimesName(x10)
)
return x1 > 0 ? [getBaseTenTimesName(x10), "'", NAMES.and.slice(1), ' ', ones(x1)].join('') : getBaseTenTimesName(x10)
}

export default tens

+ 20
- 33
src/systems/tl/getKiloCount.test.ts View File

@@ -23,7 +23,7 @@ describe.each`
${7} | ${'pitongdaan'}
${8} | ${'walongdaan'}
${9} | ${'siyamnaraan'}
`('on $hundreds in hundreds place', ({ hundreds, hundredsName, }) => {
`('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => {
describe('on 0 in tens place', () => {
test.each`
ones | onesName
@@ -37,13 +37,10 @@ describe.each`
${7} | ${' at pito'}
${8} | ${' at walo'}
${9} | ${' at siyam'}
`(`should return "${hundredsName}$onesName" for ${hundreds}0$ones`, ({ ones, onesName, }) => {
expect(getKiloCount(hundreds, 0, ones)).toBe([
hundredsName,
onesName
].join(''))
})
`(`should return "${hundredsName}$onesName" for ${hundreds}0$ones`, ({ ones, onesName }) => {
expect(getKiloCount(hundreds, 0, ones)).toBe([hundredsName, onesName].join(''))
})
})

describe('on 1 in tens place', () => {
test.each`
@@ -58,13 +55,10 @@ describe.each`
${7} | ${' labimpito'}
${8} | ${' labingwalo'}
${9} | ${' labinsiyam'}
`(`should return "${hundredsName}$tenPlusName" for ${hundreds}1$ones`, ({ ones, tenPlusName, }) => {
expect(getKiloCount(hundreds, 1, ones)).toBe([
hundredsName,
tenPlusName
].join(''))
})
`(`should return "${hundredsName}$tenPlusName" for ${hundreds}1$ones`, ({ ones, tenPlusName }) => {
expect(getKiloCount(hundreds, 1, ones)).toBe([hundredsName, tenPlusName].join(''))
})
})

describe.each`
tens | tensName
@@ -76,31 +70,24 @@ describe.each`
${7} | ${' pitumpu'}
${8} | ${' walumpu'}
${9} | ${' siyamnapu'}
`('on $tens in tens place', ({ tens, tensName, }) => {
`('on $tens in tens place', ({ tens, tensName }) => {
it(`should return "${hundredsName} at${tensName}" for ${hundreds}${tens}0`, () => {
expect(getKiloCount(hundreds, tens, 0)).toBe([
hundredsName,
tensName,
].join(' at'))
expect(getKiloCount(hundreds, tens, 0)).toBe([hundredsName, tensName].join(' at'))
})

test.each`
ones | onesName
${1} | ${'\'t isa'}
${2} | ${'\'t dalawa'}
${3} | ${'\'t tatlo'}
${4} | ${'\'t apat'}
${5} | ${'\'t lima'}
${6} | ${'\'t anim'}
${7} | ${'\'t pito'}
${8} | ${'\'t walo'}
${9} | ${'\'t siyam'}
`(`should return "${hundredsName}${tensName}$onesName" for ${hundreds}${tens}$ones`, ({ ones, onesName, }) => {
expect(getKiloCount(hundreds, tens, ones)).toBe([
hundredsName,
tensName,
onesName
].join(''))
${1} | ${"'t isa"}
${2} | ${"'t dalawa"}
${3} | ${"'t tatlo"}
${4} | ${"'t apat"}
${5} | ${"'t lima"}
${6} | ${"'t anim"}
${7} | ${"'t pito"}
${8} | ${"'t walo"}
${9} | ${"'t siyam"}
`(`should return "${hundredsName}${tensName}$onesName" for ${hundreds}${tens}$ones`, ({ ones, onesName }) => {
expect(getKiloCount(hundreds, tens, ones)).toBe([hundredsName, tensName, onesName].join(''))
})
})
})

+ 5
- 23
src/systems/tl/getKiloCount.ts View File

@@ -1,13 +1,9 @@
import NAMES from './names.json'
import { GetKiloCount, } from '../../common/NumberSystem'
import { GetKiloCount } from '../../NumberSystem'
import constructTens from './construct/tens'
import hundredTimes from './base/hundredTimes'

const getKiloCount: GetKiloCount = (
x100,
x10,
x1
) => {
const getKiloCount: GetKiloCount = (x100, x10, x1) => {
if (x100 < 1) {
return constructTens(x10, x1)
}
@@ -16,26 +12,12 @@ const getKiloCount: GetKiloCount = (
if (x1 === 0) {
return hundredTimes(x100)
}
return [
hundredTimes(x100),
NAMES.and,
constructTens(0, x1),
]
.join(' ')
return [hundredTimes(x100), NAMES.and, constructTens(0, x1)].join(' ')
}
if (x1 === 0) {
return [
hundredTimes(x100),
NAMES.and,
constructTens(x10, x1),
]
.join(' ')
return [hundredTimes(x100), NAMES.and, constructTens(x10, x1)].join(' ')
}
return [
hundredTimes(x100),
constructTens(x10, x1),
]
.join(' ')
return [hundredTimes(x100), constructTens(x10, x1)].join(' ')
}

export default getKiloCount

+ 54
- 0
tests/Converter.test.ts View File

@@ -0,0 +1,54 @@
import fs from 'fs'
import Converter from '../src'
import English from '../src/systems/en'

describe.each`
name | system | scale
${'English'} | ${English} | ${'short'}
${'English'} | ${English} | ${'long'}
`('$name ($scale count)', ({ system, scale, }) => {
let converter: Converter

beforeAll(() => {
converter = new Converter(system)
})

describe('on values', () => {
test.each`
value | name
${1000000} | ${'one million'}
${123456789} | ${'one hundred twenty three million four hundred fifty six thousand seven hundred eighty nine'}
`('should parse $value as $name', ({ value, name, }) => {
expect(converter.convert(value, { scale })).toBe(name)
})
})

describe('on streams', () => {
const ENCODING = 'utf-8'

test.each([
'million.txt'
])('should correctly parse a stream', async (filename) => {
const inputStream = fs.createReadStream(
`./tests/input/${filename}`,
{
encoding: ENCODING,
highWaterMark: 3, // this is required to parse kilos correctly
}
)
const readStream = converter.readStream({
scale,
encoding: ENCODING
})
inputStream
.pipe(readStream)
.pipe(fs.createWriteStream(`./tests/output/${filename}`))

return new Promise((resolve) => {
readStream.on('end', () => {
resolve('Hello')
})
})
})
})
})

+ 1
- 0
tests/input/million.txt View File

@@ -0,0 +1 @@
987000321

+ 5
- 0
yarn.lock View File

@@ -1155,6 +1155,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.27.tgz#a151873af5a5e851b51b3b065c9e63390a9e0eb1"
integrity sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==

"@types/node@^14.6.0":
version "14.6.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.0.tgz#7d4411bf5157339337d7cff864d9ff45f177b499"
integrity sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA==

"@types/parse-json@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"