1# -*- coding: utf-8 -*- 2# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. 3# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. 4 5# This library is free software; you can redistribute it and/or 6# modify it under the terms of the GNU Lesser General Public 7# License as published by the Free Software Foundation; either 8# version 2.1 of the License, or (at your option) any later version. 9# This library is distributed in the hope that it will be useful, 10# but WITHOUT ANY WARRANTY; without even the implied warranty of 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12# Lesser General Public License for more details. 13# You should have received a copy of the GNU Lesser General Public 14# License along with this library; if not, write to the Free Software 15# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 16# MA 02110-1301 USA 17 18from __future__ import print_function, unicode_literals 19 20 21class Num2Word_ID(): 22 BASE = {0: [], 23 1: ["satu"], 24 2: ["dua"], 25 3: ["tiga"], 26 4: ["empat"], 27 5: ["lima"], 28 6: ["enam"], 29 7: ["tujuh"], 30 8: ["delapan"], 31 9: ["sembilan"]} 32 33 TENS_TO = {3: "ribu", 34 6: "juta", 35 9: "miliar", 36 12: "triliun", 37 15: "kuadriliun", 38 18: "kuantiliun", 39 21: "sekstiliun", 40 24: "septiliun", 41 27: "oktiliun", 42 30: "noniliun", 43 33: "desiliun"} 44 45 errmsg_floatord = "Cannot treat float number as ordinal" 46 errmsg_negord = "Cannot treat negative number as ordinal" 47 errmsg_toobig = "Too large" 48 max_num = 10 ** 36 49 50 def split_by_koma(self, number): 51 return str(number).split('.') 52 53 def split_by_3(self, number): 54 """ 55 starting here, it groups the number by three from the tail 56 '1234567' -> (('1',),('234',),('567',)) 57 :param number:str 58 :rtype:tuple 59 """ 60 blocks = () 61 length = len(number) 62 63 if length < 3: 64 blocks += ((number,),) 65 else: 66 len_of_first_block = length % 3 67 68 if len_of_first_block > 0: 69 first_block = number[0:len_of_first_block], 70 blocks += first_block, 71 72 for i in range(len_of_first_block, length, 3): 73 next_block = (number[i:i + 3],), 74 blocks += next_block 75 76 return blocks 77 78 def spell(self, blocks): 79 """ 80 it adds the list of spelling to the blocks 81 ( 82 ('1',),('034',)) -> (('1',['satu']),('234',['tiga', 'puluh', 'empat']) 83 ) 84 :param blocks: tuple 85 :rtype: tuple 86 """ 87 word_blocks = () 88 first_block = blocks[0] 89 if len(first_block[0]) == 1: 90 if first_block[0] == '0': 91 spelling = ['nol'] 92 else: 93 spelling = self.BASE[int(first_block[0])] 94 elif len(first_block[0]) == 2: 95 spelling = self.puluh(first_block[0]) 96 else: 97 spelling = ( 98 self.ratus(first_block[0][0]) + self.puluh(first_block[0][1:3]) 99 ) 100 101 word_blocks += (first_block[0], spelling), 102 103 for block in blocks[1:]: 104 spelling = self.ratus(block[0][0]) + self.puluh(block[0][1:3]) 105 block += spelling, 106 word_blocks += block, 107 108 return word_blocks 109 110 def ratus(self, number): 111 # it is used to spell 112 if number == '1': 113 return ['seratus'] 114 elif number == '0': 115 return [] 116 else: 117 return self.BASE[int(number)] + ['ratus'] 118 119 def puluh(self, number): 120 # it is used to spell 121 if number[0] == '1': 122 if number[1] == '0': 123 return ['sepuluh'] 124 elif number[1] == '1': 125 return ['sebelas'] 126 else: 127 return self.BASE[int(number[1])] + ['belas'] 128 elif number[0] == '0': 129 return self.BASE[int(number[1])] 130 else: 131 return ( 132 self.BASE[int(number[0])] + ['puluh'] 133 + self.BASE[int(number[1])] 134 ) 135 136 def spell_float(self, float_part): 137 # spell the float number 138 word_list = [] 139 for n in float_part: 140 if n == '0': 141 word_list += ['nol'] 142 continue 143 word_list += self.BASE[int(n)] 144 return ' '.join(['', 'koma'] + word_list) 145 146 def join(self, word_blocks, float_part): 147 """ 148 join the words by first join lists in the tuple 149 :param word_blocks: tuple 150 :rtype: str 151 """ 152 word_list = [] 153 length = len(word_blocks) - 1 154 first_block = word_blocks[0], 155 start = 0 156 157 if length == 1 and first_block[0][0] == '1': 158 word_list += ['seribu'] 159 start = 1 160 161 for i in range(start, length + 1, 1): 162 word_list += word_blocks[i][1] 163 if not word_blocks[i][1]: 164 continue 165 if i == length: 166 break 167 word_list += [self.TENS_TO[(length - i) * 3]] 168 169 return ' '.join(word_list) + float_part 170 171 def to_cardinal(self, number): 172 if number >= self.max_num: 173 raise OverflowError(self.errmsg_toobig % (number, self.max_num)) 174 minus = '' 175 if number < 0: 176 minus = 'min ' 177 float_word = '' 178 n = self.split_by_koma(abs(number)) 179 if len(n) == 2: 180 float_word = self.spell_float(n[1]) 181 return minus + self.join(self.spell(self.split_by_3(n[0])), float_word) 182 183 def to_ordinal(self, number): 184 self.verify_ordinal(number) 185 out_word = self.to_cardinal(number) 186 if out_word == "satu": 187 return "pertama" 188 return "ke" + out_word 189 190 def to_ordinal_num(self, number): 191 self.verify_ordinal(number) 192 return "ke-" + str(number) 193 194 def to_currency(self, value): 195 return self.to_cardinal(value) + " rupiah" 196 197 def to_year(self, value): 198 return self.to_cardinal(value) 199 200 def verify_ordinal(self, value): 201 if not value == int(value): 202 raise TypeError(self.errmsg_floatord % value) 203 if not abs(value) == value: 204 raise TypeError(self.errmsg_negord % value) 205