1 package pl.matsuo.core.util;
2
3 import java.math.BigDecimal;
4
5 import static java.math.BigDecimal.*;
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 public abstract class NumberSpeaker {
34
35 private static final String[] teens = { "", "jeden", "dwa", "trzy", "cztery", "pięć", "sześć",
36 "siedem", "osiem", "dziewięć", "dziesięć", "jedenaście", "dwanaście", "trzynaście",
37 "czternaście", "piętnaście", "szesnaście", "siedemnaście", "osiemnaście", "dziewiętnaście" };
38 private static final String _20 = "dwadzieścia";
39 private static final String _30 = "trzydzieści";
40 private static final String _40 = "czterdzieści";
41 private static final String _1e1 = "dziesiąt";
42 private static final String _100 = "sto";
43 private static final String _200 = "dwieście";
44 private static final String _300 = "trzysta";
45 private static final String _400 = "czterysta";
46 private static final String _1e2 = "set";
47 private static final String _1000 = "tysiąc";
48
49 private static final String[] _1e3suff = { "ące", "ęcy" };
50 private static final String[] _1e6suff = { "y", "ów" };
51
52 private static final String _1e3 = "tysi";
53
54 private static final String _1e6 = "milion";
55 private static final String _1e9 = "miliard";
56 private static final String _1e12 = "bilion";
57 private static final String _1e15 = "biliard";
58 private static final String _1e18 = "trylion";
59
60 private static final String _1e21 = "tryliard";
61 private static final String _1e24 = "kwadrylion";
62
63 private static final String[] zloteSuffixes = { "złoty",
64 "złote",
65 "złotych"
66 };
67 private static final String[] groszeSuffixes = { "grosz",
68 "grosze",
69 "groszy",
70 "groszy",
71 };
72
73 private static final int secSize = 3;
74
75
76
77
78
79
80
81
82 public static String speakNumber(long value) {
83 StringBuffer buffer = new StringBuffer();
84 String stringValue = String.valueOf(value);
85
86 int length = stringValue.length();
87 int steps = length / secSize;
88 int remain = length % secSize;
89 if (length < secSize) {
90 steps = 0;
91 }
92 if (remain != 0) {
93 steps++;
94 }
95
96 for (int i = 1; i <= steps; i++) {
97 int begin = length - (i * secSize);
98 if (begin < 0) {
99 begin = 0;
100 }
101 int end = length - ((i - 1) * secSize);
102 String subValue = stringValue.substring(begin, end);
103
104 buffer.insert(0, decode(subValue) + " " + determineSuffix(subValue, i) + " ");
105 }
106
107 return buffer.toString().trim();
108 }
109
110 public static String speakNumber(int value) {
111 return speakNumber((long) value);
112 }
113
114 public static String speakNumber(byte value) {
115 return speakNumber((long) value);
116 }
117
118 public static String speakNumber(String value) {
119 return speakNumber(Long.parseLong(value));
120 }
121
122
123
124
125
126
127
128
129
130 private static String decode(String number) {
131 String retval;
132 int num = Integer.parseInt(number);
133
134 if (num < 20) {
135 retval = (teens[num]);
136 } else if ((num >= 20) && (num < 30)) {
137 retval = (_20 + " " + teens[num - 20]);
138 } else if ((num >= 30) && (num < 40)) {
139 retval = (_30 + " " + teens[num - 30]);
140 } else if ((num >= 40) && (num < 50)) {
141 retval = (_40 + " " + teens[num - 40]);
142 } else if ((num >= 50) && (num < 100)) {
143 int i = num / 10;
144 int j = num % 10;
145 retval = (teens[i] + _1e1 + " " + teens[j]);
146 } else if ((num >= 100) && (num < 200)) {
147 retval = (_100 + " " + decode(num % 100));
148 } else if ((num >= 200) && (num < 300)) {
149 retval = (_200 + " " + decode(num % 200));
150 } else if ((num >= 300) && (num < 400)) {
151 retval = (_300 + " " + decode(num % 300));
152 } else if ((num >= 400) && (num < 500)) {
153 retval = (_400 + " " + decode(num % 400));
154 } else if ((num >= 500) && (num < 1000)) {
155 int i = num / 100;
156 int j = num % 100;
157 retval = (teens[i] + _1e2 + " " + decode(j));
158 } else
159 retval = null;
160 return retval;
161 }
162
163
164
165
166 private static String decode(int number) {
167 return decode(String.valueOf(number));
168 }
169
170
171
172
173
174
175
176
177
178
179 private static String determineSuffix(String number, int position) {
180 String suffix = "";
181 if (number.equals("000")) {
182 return suffix;
183 }
184
185 switch (position) {
186 case 1:
187 return suffix;
188 case 2:
189 if (number.endsWith("1") && (number.length() == 1))
190 suffix = _1000;
191 if (!(number.endsWith("1") && number.length() == 1)) {
192 suffix = _1e3;
193 suffix += suffixHelper(number, _1e3suff);
194 }
195 return suffix;
196 case 3:
197 suffix = _1e6;
198 break;
199 case 4:
200 suffix = _1e9;
201 break;
202 case 5:
203 suffix = _1e12;
204 break;
205 case 6:
206 suffix = _1e15;
207 break;
208 case 7:
209 suffix = _1e18;
210 break;
211 }
212
213 if (!(number.endsWith("1") && number.length() == 1))
214 suffix += suffixHelper(number, _1e6suff);
215 return suffix;
216 }
217
218
219
220
221
222
223
224
225 private static String suffixHelper(String number, String[] suffixes) {
226
227 if (number.equals("")) {
228 return "";
229 }
230 if ((number.endsWith("11")) || (number.endsWith("12")) || (number.endsWith("13"))
231 || (number.endsWith("14"))) {
232 return suffixes[1];
233 } else {
234 if ((number.endsWith("2")) || (number.endsWith("3")) || (number.endsWith("4"))) {
235 return suffixes[0];
236 } else {
237 return suffixes[1];
238 }
239 }
240 }
241
242 private static String currencyDeclension(long number, String[] suffixes) {
243 long unities = number % 10;
244 long tens = (number-unities)/10 % 10;
245 if (unities == 1)
246 if(suffixes.length == 4 && tens > 0)
247 return suffixes[3];
248 else
249 return suffixes[0];
250 if (unities > 1 && unities < 5)
251 return suffixes[1];
252 if (unities == 0 || unities > 5)
253 return suffixes[2];
254 return null;
255 }
256
257
258 public static String speakCashAmount(BigDecimal value) {
259 String result = "";
260
261 if (value.compareTo(ZERO) < 0) {
262 result += "minus ";
263 value = value.abs();
264 }
265
266 String upperPart = "";
267 if (value.longValue() != 0)
268 upperPart = speakNumber(value.longValue()) + " "
269 + currencyDeclension(value.longValue(), zloteSuffixes);
270 long lowerPart = (long) (value.doubleValue() * 100 % 100);
271 if (lowerPart == 0)
272 result += upperPart + " zero ";
273 else
274 result += upperPart + " " + speakNumber(lowerPart) + " ";
275 result += currencyDeclension(lowerPart, groszeSuffixes);
276 return result.trim().replaceAll(" ", " ");
277 }
278 }