Browse Source

Implement German and Tagalog fundamentals

Increase test coverage on separate number systems.
master
TheoryOfNekomata 4 years ago
parent
commit
5dd94f67f8
43 changed files with 1821 additions and 21 deletions
  1. +28
    -0
      src/systems/de/base/hundredTimes.test.ts
  2. +21
    -0
      src/systems/de/base/hundredTimes.ts
  3. +187
    -0
      src/systems/de/base/kilo/combiningPrefix.test.ts
  4. +109
    -0
      src/systems/de/base/kilo/combiningPrefix.ts
  5. +28
    -0
      src/systems/de/base/kilo/hundreds.test.ts
  6. +9
    -0
      src/systems/de/base/kilo/hundreds.ts
  7. +49
    -0
      src/systems/de/base/kilo/ones.test.ts
  8. +13
    -0
      src/systems/de/base/kilo/ones.ts
  9. +28
    -0
      src/systems/de/base/kilo/tens.test.ts
  10. +9
    -0
      src/systems/de/base/kilo/tens.ts
  11. +30
    -0
      src/systems/de/base/ones.test.ts
  12. +14
    -0
      src/systems/de/base/ones.ts
  13. +29
    -0
      src/systems/de/base/tenPlus.test.ts
  14. +14
    -0
      src/systems/de/base/tenPlus.ts
  15. +28
    -0
      src/systems/de/base/tenTimes.test.ts
  16. +14
    -0
      src/systems/de/base/tenTimes.ts
  17. +77
    -0
      src/systems/de/construct/tens.test.ts
  18. +35
    -0
      src/systems/de/construct/tens.ts
  19. +129
    -0
      src/systems/de/getLongKiloName.test.ts
  20. +33
    -0
      src/systems/de/getLongKiloName.ts
  21. +5
    -1
      src/systems/de/names.json
  22. +1
    -1
      src/systems/en/base/tenPlus.ts
  23. +28
    -0
      src/systems/tl/base/hundredTimes.test.ts
  24. +59
    -0
      src/systems/tl/base/hundredTimes.ts
  25. +187
    -0
      src/systems/tl/base/kilo/combiningPrefix.test.ts
  26. +109
    -0
      src/systems/tl/base/kilo/combiningPrefix.ts
  27. +28
    -0
      src/systems/tl/base/kilo/hundreds.test.ts
  28. +9
    -0
      src/systems/tl/base/kilo/hundreds.ts
  29. +49
    -0
      src/systems/tl/base/kilo/ones.test.ts
  30. +13
    -0
      src/systems/tl/base/kilo/ones.ts
  31. +28
    -0
      src/systems/tl/base/kilo/tens.test.ts
  32. +9
    -0
      src/systems/tl/base/kilo/tens.ts
  33. +30
    -0
      src/systems/tl/base/ones.test.ts
  34. +14
    -0
      src/systems/tl/base/ones.ts
  35. +29
    -0
      src/systems/tl/base/tenPlus.test.ts
  36. +14
    -0
      src/systems/tl/base/tenPlus.ts
  37. +28
    -0
      src/systems/tl/base/tenTimes.test.ts
  38. +14
    -0
      src/systems/tl/base/tenTimes.ts
  39. +80
    -0
      src/systems/tl/construct/tens.test.ts
  40. +37
    -0
      src/systems/tl/construct/tens.ts
  41. +106
    -0
      src/systems/tl/getKiloCount.test.ts
  42. +41
    -0
      src/systems/tl/getKiloCount.ts
  43. +19
    -19
      src/systems/tl/names.json

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

@@ -0,0 +1,28 @@
import hundredTimes from './hundredTimes'

it('should exist', () => {
expect(hundredTimes).toBeDefined()
})

it('should be a callable', () => {
expect(typeof hundredTimes).toBe('function')
})

it('should accept 1 argument', () => {
expect(hundredTimes).toHaveLength(1)
})

test.each`
value | display | name
${1} | ${'100'} | ${'einhundert'}
${2} | ${'200'} | ${'zweihundert'}
${3} | ${'300'} | ${'dreihundert'}
${4} | ${'400'} | ${'vierhundert'}
${5} | ${'500'} | ${'fünfhundert'}
${6} | ${'600'} | ${'sechshundert'}
${7} | ${'700'} | ${'siebenhundert'}
${8} | ${'800'} | ${'achthundert'}
${9} | ${'900'} | ${'neunhundert'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(hundredTimes(value)).toBe(name)
})

+ 21
- 0
src/systems/de/base/hundredTimes.ts View File

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

interface HundredTimes {
(x100: number): string
}

/**
* Get the name of some number in the hundreds place.
* @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('')
)

export default hundredTimes

+ 187
- 0
src/systems/de/base/kilo/combiningPrefix.test.ts View File

@@ -0,0 +1,187 @@
import combiningPrefix from './combiningPrefix'

it('should exist', () => {
expect(combiningPrefix).toBeDefined()
})

it('should be a callable', () => {
expect(typeof combiningPrefix).toBe('function')
})

it('should accept 4 arguments', () => {
expect(combiningPrefix).toHaveLength(4)
})

describe('on 0 in hundreds place', () => {
describe('on 0 in tens place', () => {
test.each`
value | display | name
${1} | ${'1'} | ${'mi'}
${2} | ${'2'} | ${'bi'}
${3} | ${'3'} | ${'tri'}
${4} | ${'4'} | ${'quadri'}
${5} | ${'5'} | ${'quinti'}
${6} | ${'6'} | ${'sexti'}
${7} | ${'7'} | ${'septi'}
${8} | ${'8'} | ${'octi'}
${9} | ${'9'} | ${'noni'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(combiningPrefix(0, 0, value)).toBe(name)
})
})

describe.each`
tens | tensName
${1} | ${'deci'}
${2} | ${'viginti'}
${3} | ${'triginti'}
${4} | ${'quadraginti'}
${5} | ${'quinquaginti'}
${6} | ${'sexaginti'}
${7} | ${'septuaginti'}
${8} | ${'octoginti'}
${9} | ${'nonaginti'}
`('on $tens in tens place', ({ tens, tensName, }) => {
test.each`
ones | display
${0} | ${tensName}
${1} | ${'un' + tensName}
${2} | ${'duo' + tensName}
${3} | ${'tre' + tensName}
${4} | ${'quattuor' + tensName}
${5} | ${'quin' + tensName}
${6} | ${'sex' + tensName}
${7} | ${'septen' + tensName}
${8} | ${'octo' + tensName}
${9} | ${'novem' + tensName}
`(`should return "$display" for ${tens}$ones`, ({ ones, display, }) => {
expect(combiningPrefix(0, 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'}
`('on $hundreds in hundreds place', ({ hundreds, hundredsName, }) => {
describe.each`
tens | tensName
${0} | ${'ti'}
${1} | ${'deci'}
${2} | ${'viginti'}
${3} | ${'triginti'}
${4} | ${'quadraginti'}
${5} | ${'quinquaginti'}
${6} | ${'sexaginti'}
${7} | ${'septuaginti'}
${8} | ${'octoginti'}
${9} | ${'nonaginti'}
`('on $tens in tens place', ({ tens, tensName, }) => {
test.each`
ones | display
${0} | ${hundredsName + tensName}
${1} | ${hundredsName + 'un' + tensName}
${2} | ${hundredsName + 'duo' + tensName}
${3} | ${hundredsName + 'tre' + tensName}
${4} | ${hundredsName + 'quattuor' + tensName}
${5} | ${hundredsName + 'quin' + tensName}
${6} | ${hundredsName + 'sex' + tensName}
${7} | ${hundredsName + 'septen' + tensName}
${8} | ${hundredsName + 'octo' + tensName}
${9} | ${hundredsName + 'novem' + tensName}
`(`should return "$display" for ${hundreds}${tens}$ones`, ({ ones, display, }) => {
expect(combiningPrefix(hundreds, tens, ones)).toBe(display)
})
})
})

describe.each`
hundredThousands | hundredThousandsName
${1} | ${'cen'}
${2} | ${'duocen'}
${3} | ${'trecen'}
${4} | ${'quadringen'}
${5} | ${'quingen'}
${6} | ${'sescen'}
${7} | ${'septingen'}
${8} | ${'octingen'}
${9} | ${'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'}
`('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'}
`(`should return "$name" for $display`, ({ thousands, name, }) => {
const kiloHundreds = (
hundredThousands * 1000
+ tenThousands * 100
+ thousands / 100
)
expect(combiningPrefix(
kiloHundreds,
0,
0,
)).toBe(name)
})
})
})

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'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(combiningPrefix(value * 10000, 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'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(combiningPrefix(value * 10010, 0, 0)).toBe(name)
})


+ 109
- 0
src/systems/de/base/kilo/combiningPrefix.ts View File

@@ -0,0 +1,109 @@
import NAMES from '../../names.json'
import ones from './ones'
import tens from './tens'
import hundreds from './hundreds'

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

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

const isMillia = kiloHundredsRaw >= 10
if (isMillia) {
prefix += combiningPrefix(
Math.floor(kiloHundredsRaw / 1000),
Math.floor(kiloHundredsRaw / 100 % 10),
Math.floor(kiloHundredsRaw / 10 % 10),
kiloPower + 1,
)
kiloHundreds = kiloHundredsRaw % 10
}

const hasHundreds = kiloHundreds > 0
if (hasHundreds) {
prefix += hundreds(kiloHundreds)
}

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)
)
)
)
) {
// 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
prefix += ones(
kiloOnes,
special
)
if (special && [5, 6].includes(kiloOnes)) {
prefix += 't'
}
}
if (kiloTens > 0) {
prefix += tens(kiloTens)
}

if (kiloPower > 0) {
if (!(
kiloHundreds === 0
&& kiloTens === 0
&& kiloOnes === 0
)) {
for (let p = 0; p < kiloPower; p += 1) {
prefix += NAMES.kiloThousand
}
}
return prefix
}

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

export default combiningPrefix

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

@@ -0,0 +1,28 @@
import hundreds from './hundreds'

it('should exist', () => {
expect(hundreds).toBeDefined()
})

it('should be a callable', () => {
expect(typeof hundreds).toBe('function')
})

it('should accept 1 argument', () => {
expect(hundreds).toHaveLength(1)
})

test.each`
value | display | name
${1} | ${'100'} | ${'cen'}
${2} | ${'200'} | ${'duocen'}
${3} | ${'300'} | ${'trecen'}
${4} | ${'400'} | ${'quadringen'}
${5} | ${'500'} | ${'quingen'}
${6} | ${'600'} | ${'sescen'}
${7} | ${'700'} | ${'septingen'}
${8} | ${'800'} | ${'octingen'}
${9} | ${'900'} | ${'nongen'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(hundreds(value)).toBe(name)
})

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

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

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

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

export default hundreds

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

@@ -0,0 +1,49 @@
import ones from './ones'

it('should exist', () => {
expect(ones).toBeDefined()
})

it('should be a callable', () => {
expect(typeof ones).toBe('function')
})

it('should accept 2 arguments', () => {
expect(ones).toHaveLength(2)
})

describe('on ordinary units', () => {
test.each`
value | display | name
${0} | ${'0'} | ${''}
${1} | ${'1'} | ${'un'}
${2} | ${'2'} | ${'duo'}
${3} | ${'3'} | ${'tre'}
${4} | ${'4'} | ${'quattuor'}
${5} | ${'5'} | ${'quin'}
${6} | ${'6'} | ${'sex'}
${7} | ${'7'} | ${'septen'}
${8} | ${'8'} | ${'octo'}
${9} | ${'9'} | ${'novem'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(ones(value, false)).toBe(name)
})
})

describe('on special units', () => {
test.each`
value | display | name
${0} | ${'0'} | ${''}
${1} | ${'1'} | ${'m'}
${2} | ${'2'} | ${'b'}
${3} | ${'3'} | ${'tr'}
${4} | ${'4'} | ${'quadr'}
${5} | ${'5'} | ${'quin'}
${6} | ${'6'} | ${'sex'}
${7} | ${'7'} | ${'sept'}
${8} | ${'8'} | ${'oct'}
${9} | ${'9'} | ${'non'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(ones(value, true)).toBe(name)
})
})

+ 13
- 0
src/systems/de/base/kilo/ones.ts View File

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

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

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

export default ones

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

@@ -0,0 +1,28 @@
import tens from './tens'

it('should exist', () => {
expect(tens).toBeDefined()
})

it('should be a callable', () => {
expect(typeof tens).toBe('function')
})

it('should accept 1 argument', () => {
expect(tens).toHaveLength(1)
})

test.each`
value | display | name
${1} | ${'10'} | ${'dec'}
${2} | ${'20'} | ${'vigin'}
${3} | ${'30'} | ${'trigin'}
${4} | ${'40'} | ${'quadragin'}
${5} | ${'50'} | ${'quinquagin'}
${6} | ${'60'} | ${'sexagin'}
${7} | ${'70'} | ${'septuagin'}
${8} | ${'80'} | ${'octogin'}
${9} | ${'90'} | ${'nonagin'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(tens(value)).toBe(name)
})

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

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

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

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

export default tens

+ 30
- 0
src/systems/de/base/ones.test.ts View File

@@ -0,0 +1,30 @@
import ones from './ones'

it('should exist', () => {
expect(ones).toBeDefined()
})

it('should be a callable', () => {
expect(typeof ones).toBe('function')
})

it('should accept 1 argument', () => {
expect(ones).toHaveLength(1)
})

test.each`
value | display | name
${0} | ${'0'} | ${'zero'}
${1} | ${'1'} | ${'ein'}
${2} | ${'2'} | ${'zwei'}
${3} | ${'3'} | ${'drei'}
${4} | ${'4'} | ${'vier'}
${5} | ${'5'} | ${'fünf'}
${6} | ${'6'} | ${'sechs'}
${7} | ${'7'} | ${'sieben'}
${8} | ${'8'} | ${'acht'}
${9} | ${'9'} | ${'neun'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(ones(value)).toBe(name)
})


+ 14
- 0
src/systems/de/base/ones.ts View File

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

interface Ones {
(x1: number): string
}

/**
* Get the name of some number in the ones place.
* @param {number} x1 - The number in the ones place.
* @returns {string} The name of the number in the ones place.
*/
const ones: Ones = (x1) => NAMES.units[x1]

export default ones

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

@@ -0,0 +1,29 @@
import tenPlus from './tenPlus'

it('should exist', () => {
expect(tenPlus).toBeDefined()
})

it('should be a callable', () => {
expect(typeof tenPlus).toBe('function')
})

it('should accept 1 argument', () => {
expect(tenPlus).toHaveLength(1)
})

test.each`
value | display | name
${0} | ${'10'} | ${'zehn'}
${1} | ${'11'} | ${'elf'}
${2} | ${'12'} | ${'zwölf'}
${3} | ${'13'} | ${'dreizehn'}
${4} | ${'14'} | ${'vierzehn'}
${5} | ${'15'} | ${'fünfzehn'}
${6} | ${'16'} | ${'sechzehn'}
${7} | ${'17'} | ${'siebzehn'}
${8} | ${'18'} | ${'achtzehn'}
${9} | ${'19'} | ${'neunzehn'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(tenPlus(value)).toBe(name)
})

+ 14
- 0
src/systems/de/base/tenPlus.ts View File

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

interface TenPlus {
(ones: number): string
}

/**
* Get the name of some number plus ten.
* @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])

export default tenPlus

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

@@ -0,0 +1,28 @@
import tenTimes from './tenTimes'

it('should exist', () => {
expect(tenTimes).toBeDefined()
})

it('should be a callable', () => {
expect(typeof tenTimes).toBe('function')
})

it('should accept 1 argument', () => {
expect(tenTimes).toHaveLength(1)
})

test.each`
value | display | name
${1} | ${'10'} | ${'zehn'}
${2} | ${'20'} | ${'zwanzig'}
${3} | ${'30'} | ${'dreißig'}
${4} | ${'40'} | ${'vierzig'}
${5} | ${'50'} | ${'fünfzig'}
${6} | ${'60'} | ${'sechzig'}
${7} | ${'70'} | ${'siebzig'}
${8} | ${'80'} | ${'achtzig'}
${9} | ${'90'} | ${'neunzig'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(tenTimes(value)).toBe(name)
})

+ 14
- 0
src/systems/de/base/tenTimes.ts View File

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

interface TenTimes {
(x10: number): string
}

/**
* Get the name of some number in the tens place.
* @param {number} x10 - The number in the tens place.
* @returns {string} The name of the number in the tens place.
*/
const tenTimes: TenTimes = (x10) => NAMES.tenTimes[x10]

export default tenTimes

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

@@ -0,0 +1,77 @@
import tensFn from './tens'

it('should exist', () => {
expect(tensFn).toBeDefined()
})

it('should be a callable', () => {
expect(typeof tensFn).toBe('function')
})

it('should accept 2 arguments', () => {
expect(tensFn).toHaveLength(2)
})

describe('on 0 in tens place', () => {
test.each`
ones | onesName
${0} | ${'zero'}
${1} | ${'ein'}
${2} | ${'zwei'}
${3} | ${'drei'}
${4} | ${'vier'}
${5} | ${'fünf'}
${6} | ${'sechs'}
${7} | ${'sieben'}
${8} | ${'acht'}
${9} | ${'neun'}
`(`should return "$onesName" for $ones`, ({ ones, onesName, }) => {
expect(tensFn(0, ones)).toBe(onesName)
})
})

describe('on 1 in tens place', () => {
test.each`
ones | tenPlusName
${0} | ${'zehn'}
${1} | ${'elf'}
${2} | ${'zwölf'}
${3} | ${'dreizehn'}
${4} | ${'vierzehn'}
${5} | ${'fünfzehn'}
${6} | ${'sechzehn'}
${7} | ${'siebzehn'}
${8} | ${'achtzehn'}
${9} | ${'neunzehn'}
`(`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, }) => {
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, }) => {
expect(tensFn(tens, ones)).toBe(display)
})
})

+ 35
- 0
src/systems/de/construct/tens.ts View File

@@ -0,0 +1,35 @@
import NAMES from '../names.json'
import ones from '../base/ones'
import tenPlus from '../base/tenPlus'
import getBaseTenTimesName from '../base/tenTimes'

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

const tens: Tens = (x10, x1) => {
switch (x10) {
case 0:
return ones(x1)
case 1:
if (x1 > 0) {
return tenPlus(x1)
}
break
default:
break
}

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

export default tens

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

@@ -0,0 +1,129 @@
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)
})

+ 33
- 0
src/systems/de/getLongKiloName.ts View File

@@ -0,0 +1,33 @@
import { GetKiloName, } from '../../common/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

+ 5
- 1
src/systems/de/names.json View File

@@ -17,7 +17,7 @@
"zwölf",
"dreizehn",
"vierzehn",
"fünfzhen",
"fünfzehn",
"sechzehn",
"siebzehn",
"achtzehn",
@@ -38,6 +38,7 @@
"hundred": "hundert",
"thousand": "tausend",
"kiloSpecialUnits": [
"",
"m",
"b",
"tr",
@@ -49,6 +50,7 @@
"non"
],
"kiloUnits": [
"",
"un",
"duo",
"tre",
@@ -60,6 +62,7 @@
"novem"
],
"kiloTens": [
"",
"dec",
"vigin",
"trigin",
@@ -71,6 +74,7 @@
"nonagin"
],
"kiloHundreds": [
"",
"cen",
"duocen",
"trecen",


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

@@ -9,6 +9,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) => NAMES.tenPlus[x1]
const tenPlus: TenPlus = (x1) => (x1 === 0 ? NAMES.tenTimes[1] : NAMES.tenPlus[x1])

export default tenPlus

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

@@ -0,0 +1,28 @@
import hundredTimes from './hundredTimes'

it('should exist', () => {
expect(hundredTimes).toBeDefined()
})

it('should be a callable', () => {
expect(typeof hundredTimes).toBe('function')
})

it('should accept 1 argument', () => {
expect(hundredTimes).toHaveLength(1)
})

test.each`
value | display | name
${1} | ${'100'} | ${'sandaan'}
${2} | ${'200'} | ${'dalawandaan'}
${3} | ${'300'} | ${'tatlongdaan'}
${4} | ${'400'} | ${'apatnaraan'}
${5} | ${'500'} | ${'limandaan'}
${6} | ${'600'} | ${'animnaraan'}
${7} | ${'700'} | ${'pitongdaan'}
${8} | ${'800'} | ${'walongdaan'}
${9} | ${'900'} | ${'siyamnaraan'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(hundredTimes(value)).toBe(name)
})

+ 59
- 0
src/systems/tl/base/hundredTimes.ts View File

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

interface HundredTimes {
(x100: number): string
}

/**
* Get the name of some number in the hundreds place.
* @param {number} x100 - The number in the hundreds place.
* @returns {string} The name of the number in the hundreds place.
*/
const hundredTimes: HundredTimes = (x100) => {
if (x100 === 0) {
return NAMES.units[0]
}

const hundredFactor = NAMES.units[x100]
let hundredFactorCombining: string
let infix: string
let hundredSuffixCombining: string

switch (x100) {
case 1:
hundredFactorCombining = hundredFactor.slice(1)
infix = 'n'
hundredSuffixCombining = NAMES.hundred
break
case 2:
case 5:
hundredFactorCombining = hundredFactor
infix = 'n'
hundredSuffixCombining = NAMES.hundred
break
default:
case 3:
case 7:
case 8:
hundredFactorCombining = hundredFactor
infix = 'ng'
hundredSuffixCombining = NAMES.hundred
break
case 4:
case 6:
case 9:
hundredFactorCombining = hundredFactor
infix = 'na'
hundredSuffixCombining = 'r' + NAMES.hundred.slice(1)
break
}

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

export default hundredTimes

+ 187
- 0
src/systems/tl/base/kilo/combiningPrefix.test.ts View File

@@ -0,0 +1,187 @@
import combiningPrefix from './combiningPrefix'

it('should exist', () => {
expect(combiningPrefix).toBeDefined()
})

it('should be a callable', () => {
expect(typeof combiningPrefix).toBe('function')
})

it('should accept 4 arguments', () => {
expect(combiningPrefix).toHaveLength(4)
})

describe('on 0 in hundreds place', () => {
describe('on 0 in tens place', () => {
test.each`
value | display | name
${1} | ${'1'} | ${'mi'}
${2} | ${'2'} | ${'bi'}
${3} | ${'3'} | ${'tri'}
${4} | ${'4'} | ${'kuwadri'}
${5} | ${'5'} | ${'kuwinti'}
${6} | ${'6'} | ${'seksti'}
${7} | ${'7'} | ${'septi'}
${8} | ${'8'} | ${'okti'}
${9} | ${'9'} | ${'noni'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(combiningPrefix(0, 0, value)).toBe(name)
})
})

describe.each`
tens | tensName
${1} | ${'desi'}
${2} | ${'bihinti'}
${3} | ${'trihinti'}
${4} | ${'kuwadrahinti'}
${5} | ${'kuwinkuwahinti'}
${6} | ${'seksahinti'}
${7} | ${'septuwahinti'}
${8} | ${'oktohinti'}
${9} | ${'nonahinti'}
`('on $tens in tens place', ({ tens, tensName, }) => {
test.each`
ones | display
${0} | ${tensName}
${1} | ${'un' + tensName}
${2} | ${'duwo' + tensName}
${3} | ${'tre' + tensName}
${4} | ${'kuwatuwor' + tensName}
${5} | ${'kuwin' + tensName}
${6} | ${'seks' + tensName}
${7} | ${'septen' + tensName}
${8} | ${'okto' + tensName}
${9} | ${'nobem' + tensName}
`(`should return "$display" for ${tens}$ones`, ({ ones, display, }) => {
expect(combiningPrefix(0, 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'}
`('on $hundreds in hundreds place', ({ hundreds, hundredsName, }) => {
describe.each`
tens | tensName
${0} | ${'ti'}
${1} | ${'desi'}
${2} | ${'bihinti'}
${3} | ${'trihinti'}
${4} | ${'kuwadrahinti'}
${5} | ${'kuwinkuwahinti'}
${6} | ${'seksahinti'}
${7} | ${'septuwahinti'}
${8} | ${'oktohinti'}
${9} | ${'nonahinti'}
`('on $tens in tens place', ({ tens, tensName, }) => {
test.each`
ones | display
${0} | ${hundredsName + tensName}
${1} | ${hundredsName + 'un' + tensName}
${2} | ${hundredsName + 'duwo' + tensName}
${3} | ${hundredsName + 'tre' + tensName}
${4} | ${hundredsName + 'kuwatuwor' + tensName}
${5} | ${hundredsName + 'kuwin' + tensName}
${6} | ${hundredsName + 'seks' + tensName}
${7} | ${hundredsName + 'septen' + tensName}
${8} | ${hundredsName + 'okto' + tensName}
${9} | ${hundredsName + 'nobem' + tensName}
`(`should return "$display" for ${hundreds}${tens}$ones`, ({ ones, display, }) => {
expect(combiningPrefix(hundreds, tens, ones)).toBe(display)
})
})
})

describe.each`
hundredThousands | hundredThousandsName
${1} | ${'sen'}
${2} | ${'duwosen'}
${3} | ${'tresen'}
${4} | ${'kuwadringhen'}
${5} | ${'kuwinghen'}
${6} | ${'sesen'}
${7} | ${'septinghen'}
${8} | ${'oktinghen'}
${9} | ${'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'}
`('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'}
`(`should return "$name" for $display`, ({ thousands, name, }) => {
const kiloHundreds = (
hundredThousands * 1000
+ tenThousands * 100
+ thousands / 100
)
expect(combiningPrefix(
kiloHundreds,
0,
0,
)).toBe(name)
})
})
})

it.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'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(combiningPrefix(value * 10000, 0, 0)).toBe(name)
})

it.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'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(combiningPrefix(value * 10010, 0, 0)).toBe(name)
})


+ 109
- 0
src/systems/tl/base/kilo/combiningPrefix.ts View File

@@ -0,0 +1,109 @@
import NAMES from '../../names.json'
import ones from './ones'
import tens from './tens'
import hundreds from './hundreds'

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

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

const isMillia = kiloHundredsRaw >= 10
if (isMillia) {
prefix += combiningPrefix(
Math.floor(kiloHundredsRaw / 1000),
Math.floor(kiloHundredsRaw / 100 % 10),
Math.floor(kiloHundredsRaw / 10 % 10),
kiloPower + 1,
)
kiloHundreds = kiloHundredsRaw % 10
}

const hasHundreds = kiloHundreds > 0
if (hasHundreds) {
prefix += hundreds(kiloHundreds)
}

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)
)
)
)
) {
// 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
prefix += ones(
kiloOnes,
special
)
if (special && [5, 6].includes(kiloOnes)) {
prefix += 't'
}
}
if (kiloTens > 0) {
prefix += tens(kiloTens)
}

if (kiloPower > 0) {
if (!(
kiloHundreds === 0
&& kiloTens === 0
&& kiloOnes === 0
)) {
for (let p = 0; p < kiloPower; p += 1) {
prefix += NAMES.kiloThousand
}
}
return prefix
}

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

export default combiningPrefix

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

@@ -0,0 +1,28 @@
import hundreds from './hundreds'

it('should exist', () => {
expect(hundreds).toBeDefined()
})

it('should be a callable', () => {
expect(typeof hundreds).toBe('function')
})

it('should accept 1 argument', () => {
expect(hundreds).toHaveLength(1)
})

test.each`
value | display | name
${1} | ${'100'} | ${'sen'}
${2} | ${'200'} | ${'duwosen'}
${3} | ${'300'} | ${'tresen'}
${4} | ${'400'} | ${'kuwadringhen'}
${5} | ${'500'} | ${'kuwinghen'}
${6} | ${'600'} | ${'sesen'}
${7} | ${'700'} | ${'septinghen'}
${8} | ${'800'} | ${'oktinghen'}
${9} | ${'900'} | ${'nonghen'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(hundreds(value)).toBe(name)
})

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

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

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

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

export default hundreds

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

@@ -0,0 +1,49 @@
import ones from './ones'

it('should exist', () => {
expect(ones).toBeDefined()
})

it('should be a callable', () => {
expect(typeof ones).toBe('function')
})

it('should accept 2 arguments', () => {
expect(ones).toHaveLength(2)
})

describe('on ordinary units', () => {
test.each`
value | display | name
${0} | ${'0'} | ${''}
${1} | ${'1'} | ${'un'}
${2} | ${'2'} | ${'duwo'}
${3} | ${'3'} | ${'tre'}
${4} | ${'4'} | ${'kuwatuwor'}
${5} | ${'5'} | ${'kuwin'}
${6} | ${'6'} | ${'seks'}
${7} | ${'7'} | ${'septen'}
${8} | ${'8'} | ${'okto'}
${9} | ${'9'} | ${'nobem'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(ones(value, false)).toBe(name)
})
})

describe('on special units', () => {
test.each`
value | display | name
${0} | ${'0'} | ${''}
${1} | ${'1'} | ${'m'}
${2} | ${'2'} | ${'b'}
${3} | ${'3'} | ${'tr'}
${4} | ${'4'} | ${'kuwadr'}
${5} | ${'5'} | ${'kuwin'}
${6} | ${'6'} | ${'seks'}
${7} | ${'7'} | ${'sept'}
${8} | ${'8'} | ${'okt'}
${9} | ${'9'} | ${'non'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(ones(value, true)).toBe(name)
})
})

+ 13
- 0
src/systems/tl/base/kilo/ones.ts View File

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

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

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

export default ones

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

@@ -0,0 +1,28 @@
import tens from './tens'

it('should exist', () => {
expect(tens).toBeDefined()
})

it('should be a callable', () => {
expect(typeof tens).toBe('function')
})

it('should accept 1 argument', () => {
expect(tens).toHaveLength(1)
})

test.each`
value | display | name
${1} | ${'10'} | ${'des'}
${2} | ${'20'} | ${'bihin'}
${3} | ${'30'} | ${'trihin'}
${4} | ${'40'} | ${'kuwadrahin'}
${5} | ${'50'} | ${'kuwinkuwahin'}
${6} | ${'60'} | ${'seksahin'}
${7} | ${'70'} | ${'septuwahin'}
${8} | ${'80'} | ${'oktohin'}
${9} | ${'90'} | ${'nonahin'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(tens(value)).toBe(name)
})

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

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

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

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

export default tens

+ 30
- 0
src/systems/tl/base/ones.test.ts View File

@@ -0,0 +1,30 @@
import ones from './ones'

it('should exist', () => {
expect(ones).toBeDefined()
})

it('should be a callable', () => {
expect(typeof ones).toBe('function')
})

it('should accept 1 argument', () => {
expect(ones).toHaveLength(1)
})

test.each`
value | display | name
${0} | ${'0'} | ${'sero'}
${1} | ${'1'} | ${'isa'}
${2} | ${'2'} | ${'dalawa'}
${3} | ${'3'} | ${'tatlo'}
${4} | ${'4'} | ${'apat'}
${5} | ${'5'} | ${'lima'}
${6} | ${'6'} | ${'anim'}
${7} | ${'7'} | ${'pito'}
${8} | ${'8'} | ${'walo'}
${9} | ${'9'} | ${'siyam'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(ones(value)).toBe(name)
})


+ 14
- 0
src/systems/tl/base/ones.ts View File

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

interface Ones {
(x1: number): string
}

/**
* Get the name of some number in the ones place.
* @param {number} x1 - The number in the ones place.
* @returns {string} The name of the number in the ones place.
*/
const ones: Ones = (x1) => NAMES.units[x1]

export default ones

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

@@ -0,0 +1,29 @@
import tenPlus from './tenPlus'

it('should exist', () => {
expect(tenPlus).toBeDefined()
})

it('should be a callable', () => {
expect(typeof tenPlus).toBe('function')
})

it('should accept 1 argument', () => {
expect(tenPlus).toHaveLength(1)
})

test.each`
value | display | name
${0} | ${'10'} | ${'sampu'}
${1} | ${'11'} | ${'labing-isa'}
${2} | ${'12'} | ${'labindalawa'}
${3} | ${'13'} | ${'labintatlo'}
${4} | ${'14'} | ${'labing-apat'}
${5} | ${'15'} | ${'labinlima'}
${6} | ${'16'} | ${'labing-anim'}
${7} | ${'17'} | ${'labimpito'}
${8} | ${'18'} | ${'labingwalo'}
${9} | ${'19'} | ${'labinsiyam'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(tenPlus(value)).toBe(name)
})

+ 14
- 0
src/systems/tl/base/tenPlus.ts View File

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

interface TenPlus {
(ones: number): string
}

/**
* Get the name of some number plus ten.
* @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])

export default tenPlus

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

@@ -0,0 +1,28 @@
import tenTimes from './tenTimes'

it('should exist', () => {
expect(tenTimes).toBeDefined()
})

it('should be a callable', () => {
expect(typeof tenTimes).toBe('function')
})

it('should accept 1 argument', () => {
expect(tenTimes).toHaveLength(1)
})

test.each`
value | display | name
${1} | ${'10'} | ${'sampu'}
${2} | ${'20'} | ${'dalawampu'}
${3} | ${'30'} | ${'tatlumpu'}
${4} | ${'40'} | ${'apatnapu'}
${5} | ${'50'} | ${'limampu'}
${6} | ${'60'} | ${'animnapu'}
${7} | ${'70'} | ${'pitumpu'}
${8} | ${'80'} | ${'walumpu'}
${9} | ${'90'} | ${'siyamnapu'}
`('should return "$name" on $display', ({ value, name, }) => {
expect(tenTimes(value)).toBe(name)
})

+ 14
- 0
src/systems/tl/base/tenTimes.ts View File

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

interface TenTimes {
(x10: number): string
}

/**
* Get the name of some number in the tens place.
* @param {number} x10 - The number in the tens place.
* @returns {string} The name of the number in the tens place.
*/
const tenTimes: TenTimes = (x10) => NAMES.tenTimes[x10]

export default tenTimes

+ 80
- 0
src/systems/tl/construct/tens.test.ts View File

@@ -0,0 +1,80 @@
import tensFn from './tens'

it('should exist', () => {
expect(tensFn).toBeDefined()
})

it('should be a callable', () => {
expect(typeof tensFn).toBe('function')
})

it('should accept 2 arguments', () => {
expect(tensFn).toHaveLength(2)
})

describe('on 0 in tens place', () => {
test.each`
ones | onesName
${0} | ${'sero'}
${1} | ${'isa'}
${2} | ${'dalawa'}
${3} | ${'tatlo'}
${4} | ${'apat'}
${5} | ${'lima'}
${6} | ${'anim'}
${7} | ${'pito'}
${8} | ${'walo'}
${9} | ${'siyam'}
`(`should return "$onesName" for $ones`, ({ ones, onesName, }) => {
expect(tensFn(0, ones)).toBe(onesName)
})
})

describe('on 1 in tens place', () => {
test.each`
ones | tenPlusName
${0} | ${'sampu'}
${1} | ${'labing-isa'}
${2} | ${'labindalawa'}
${3} | ${'labintatlo'}
${4} | ${'labing-apat'}
${5} | ${'labinlima'}
${6} | ${'labing-anim'}
${7} | ${'labimpito'}
${8} | ${'labingwalo'}
${9} | ${'labinsiyam'}
`(`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, }) => {
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(''))
})
})

+ 37
- 0
src/systems/tl/construct/tens.ts View File

@@ -0,0 +1,37 @@
import NAMES from '../names.json'
import ones from '../base/ones'
import tenPlus from '../base/tenPlus'
import getBaseTenTimesName from '../base/tenTimes'

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

const tens: Tens = (x10, x1) => {
switch (x10) {
case 0:
return ones(x1)
case 1:
if (x1 > 0) {
return tenPlus(x1)
}
break
default:
break
}

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

export default tens

+ 106
- 0
src/systems/tl/getKiloCount.test.ts View File

@@ -0,0 +1,106 @@
import getKiloCount from './getKiloCount'

it('should exist', () => {
expect(getKiloCount).toBeDefined()
})

it('should be a callable', () => {
expect(typeof getKiloCount).toBe('function')
})

it('should accept 3 arguments', () => {
expect(getKiloCount).toHaveLength(3)
})

describe.each`
hundreds | hundredsName
${1} | ${'sandaan'}
${2} | ${'dalawandaan'}
${3} | ${'tatlongdaan'}
${4} | ${'apatnaraan'}
${5} | ${'limandaan'}
${6} | ${'animnaraan'}
${7} | ${'pitongdaan'}
${8} | ${'walongdaan'}
${9} | ${'siyamnaraan'}
`('on $hundreds in hundreds place', ({ hundreds, hundredsName, }) => {
describe('on 0 in tens place', () => {
test.each`
ones | onesName
${0} | ${''}
${1} | ${' at isa'}
${2} | ${' at dalawa'}
${3} | ${' at tatlo'}
${4} | ${' at apat'}
${5} | ${' at lima'}
${6} | ${' at anim'}
${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(''))
})
})

describe('on 1 in tens place', () => {
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'}
`(`should return "${hundredsName}$tenPlusName" for ${hundreds}1$ones`, ({ ones, tenPlusName, }) => {
expect(getKiloCount(hundreds, 1, ones)).toBe([
hundredsName,
tenPlusName
].join(''))
})
})

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, }) => {
it(`should return "${hundredsName} at${tensName}" for ${hundreds}${tens}0`, () => {
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(''))
})
})
})

+ 41
- 0
src/systems/tl/getKiloCount.ts View File

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

const getKiloCount: GetKiloCount = (
x100,
x10,
x1
) => {
if (x100 < 1) {
return constructTens(x10, x1)
}

if (x10 === 0) {
if (x1 === 0) {
return hundredTimes(x100)
}
return [
hundredTimes(x100),
NAMES.and,
constructTens(0, x1),
]
.join(' ')
}
if (x1 === 0) {
return [
hundredTimes(x100),
NAMES.and,
constructTens(x10, x1),
]
.join(' ')
}
return [
hundredTimes(x100),
constructTens(x10, x1),
]
.join(' ')
}

export default getKiloCount

+ 19
- 19
src/systems/tl/names.json View File

@@ -39,10 +39,10 @@
"thousand": "libo",
"kiloSpecialUnits": [
"",
"mi",
"bi",
"tri",
"kuwadri",
"m",
"b",
"tr",
"kuwadr",
"kuwin",
"seks",
"sept",
@@ -52,7 +52,7 @@
"kiloUnits": [
"",
"un",
"duo",
"duwo",
"tre",
"kuwatuwor",
"kuwin",
@@ -64,26 +64,26 @@
"kiloTens": [
"",
"des",
"bigin",
"trigin",
"kuwadragin",
"kuwinkuwagin",
"seksagin",
"septuwagin",
"oktogin",
"nonagin"
"bihin",
"trihin",
"kuwadrahin",
"kuwinkuwahin",
"seksahin",
"septuwahin",
"oktohin",
"nonahin"
],
"kiloHundreds": [
"",
"sen",
"duosen",
"duwosen",
"tresen",
"kuwadringen",
"kuwingen",
"kuwadringhen",
"kuwinghen",
"sesen",
"septingen",
"oktingen",
"nongen"
"septinghen",
"oktinghen",
"nonghen"
],
"kiloThousand": "milya",
"kiloEvenSuffix": "lyon",