+164
-1
src/voice.ts
+164
-1
src/voice.ts
···
1
-
1
+
import path from 'path';
2
2
3
3
interface Voice {
4
4
directory: string;
···
7
7
8
8
type Voices = { [name: string]: Voice };
9
9
10
+
const LINES = {
11
+
NEGATIVE: 'negative',
12
+
POINT: 'point',
13
+
ZERO: 'zero',
14
+
ONE: 'one',
15
+
TWO: 'two',
16
+
THREE: 'three',
17
+
FOUR: 'four',
18
+
FIVE: 'five',
19
+
SIX: 'six',
20
+
SEVEN: 'seven',
21
+
EIGHT: 'eight',
22
+
NINE: 'nine',
23
+
TEN: 'ten',
24
+
ELEVEN: 'eleven',
25
+
TWELVE: 'twelve',
26
+
THIRTEEN: 'thirteen',
27
+
FIFTEEN: 'fifteen',
28
+
TEEN: 'teen',
29
+
TWENTY: 'twenty',
30
+
THIRTY: 'thirty',
31
+
FORTY: 'forty',
32
+
FIFTY: 'fifty',
33
+
SIXTY: 'sixty',
34
+
SEVENTY: 'seventy',
35
+
EIGHTY: 'eighty',
36
+
NINETY: 'ninety',
37
+
HUNDRED: 'hundred',
38
+
THOUSAND: 'thousand',
39
+
MILLION: 'million',
40
+
BILLION: 'billion',
41
+
TRILLION: 'trillion'
42
+
}
43
+
44
+
function formatNumber(num: number): string {
45
+
const parts = num.toString().split(".");
46
+
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
47
+
return parts.join(".");
48
+
}
49
+
50
+
function digitByDigit(str: string): string[] {
51
+
const tokens: string[] = [];
52
+
const input = str.replaceAll(',', '');
53
+
const map = [
54
+
LINES.ZERO,
55
+
LINES.ONE,
56
+
LINES.TWO,
57
+
LINES.THREE,
58
+
LINES.FOUR,
59
+
LINES.FIVE,
60
+
LINES.SIX,
61
+
LINES.SEVEN,
62
+
LINES.EIGHT,
63
+
LINES.NINE
64
+
]
65
+
for (let i = 0; i < input.length; i++) {
66
+
tokens.push(map[parseInt(input.charAt(i))]);
67
+
}
68
+
return tokens;
69
+
}
70
+
71
+
function tens(str: string): string[] {
72
+
if (str === '0') {
73
+
return [LINES.ZERO];
74
+
}
75
+
const tokens: string[] = [];
76
+
const num = parseInt(str);
77
+
const map = {
78
+
'2': LINES.TWENTY,
79
+
'3': LINES.THIRTY,
80
+
'4': LINES.FORTY,
81
+
'5': LINES.FIFTY,
82
+
'6': LINES.SIXTY,
83
+
'7': LINES.SEVENTY,
84
+
'8': LINES.EIGHTY,
85
+
'9': LINES.NINETY
86
+
};
87
+
const ones = str.charAt(str.length - 1);
88
+
if (num === 0) {
89
+
return [];
90
+
}
91
+
else if (num >= 20) {
92
+
tokens.push(map[str.charAt(0)]);
93
+
if (ones !== '0') {
94
+
tokens.push(...digitByDigit(ones));
95
+
}
96
+
}
97
+
else if (num < 10) {
98
+
tokens.push(...digitByDigit(ones));
99
+
}
100
+
else {
101
+
const weirdoNumberMap = [
102
+
[LINES.TEN],
103
+
[LINES.ELEVEN],
104
+
[LINES.TWELVE],
105
+
[LINES.THIRTEEN],
106
+
[LINES.FOUR, LINES.TEEN],
107
+
[LINES.FIFTEEN],
108
+
[LINES.SIX, LINES.TEEN],
109
+
[LINES.SEVEN, LINES.TEEN],
110
+
[LINES.EIGHT, LINES.TEEN],
111
+
[LINES.NINE, LINES.TEEN],
112
+
]
113
+
tokens.push(...weirdoNumberMap[num - 10]);
114
+
}
115
+
return tokens;
116
+
}
117
+
118
+
function hundreds(str: string): string[] {
119
+
const tokens: string[] = [];
120
+
if (str.length === 3 && str.charAt(0) !== '0') {
121
+
tokens.push(...digitByDigit(str.charAt(0)));
122
+
tokens.push(LINES.HUNDRED);
123
+
str = str.substring(1);
124
+
}
125
+
tokens.push(...tens(str));
126
+
return tokens;
127
+
}
128
+
129
+
function integer(str: string): string[] {
130
+
const tokens: string[] = [];
131
+
const numGroups = str.split(',');
132
+
const seperators = [LINES.TRILLION, LINES.BILLION, LINES.MILLION, LINES.THOUSAND];
133
+
if (numGroups.length > 5) {
134
+
return digitByDigit(str);
135
+
}
136
+
seperators.splice(0, seperators.length - numGroups.length + 1);
137
+
numGroups.forEach(g => {
138
+
if (g !== '000') {
139
+
tokens.push(...hundreds(g));
140
+
}
141
+
if (seperators.length === 0) {
142
+
return;
143
+
}
144
+
const sep = seperators.shift();
145
+
if (g !== '000') {
146
+
tokens.push(sep);
147
+
}
148
+
});
149
+
return tokens;
150
+
}
151
+
152
+
function voiceLines(voice: Voice, num: number): string[] {
153
+
if (Math.abs(num) > 999999999999999 || isNaN(num)) {
154
+
return [];
155
+
}
156
+
const tokens: string[] = [];
157
+
const str = formatNumber(num);
158
+
const parts = str.split('.');
159
+
if (parts[0].startsWith('-')) {
160
+
tokens.push(LINES.NEGATIVE);
161
+
parts[0] = parts[0].substring(1);
162
+
}
163
+
tokens.push(...integer(parts[0]));
164
+
if (parts.length > 1) {
165
+
tokens.push(LINES.POINT);
166
+
tokens.push(...digitByDigit(parts[1]));
167
+
}
168
+
return tokens.map(l => path.join(voice.directory, `${l}.${voice.extension}`));
169
+
}
170
+
171
+
export default voiceLines;
172
+
export { voiceLines };
10
173
export type { Voice, Voices };