lib/extenso_pt.rb in extenso_pt-0.4.4 vs lib/extenso_pt.rb in extenso_pt-0.5.0
- old
+ new
@@ -13,87 +13,148 @@
A1000={pt: ["","CEM","CENTO","DUZENTOS","TREZENTOS","QUATROCENTOS","QUINHENTOS","SEISCENTOS","SETECENTOS","OITOCENTOS","NOVECENTOS"],
br: ["","CEM","CENTO","DUZENTOS","TREZENTOS","QUATROCENTOS","QUINHENTOS","SEISCENTOS","SETECENTOS","OITOCENTOS","NOVECENTOS"]}
A1e24={pt: ["","MIL"," MILHÃO"," MIL MILHÃO"," BILIÃO"," MIL BILIÃO"," TRILIÃO"," MIL TRILIÃO",""," MIL"," MILHÕES"," MIL MILHÕES"," BILIÕES"," MIL BILIÕES"," TRILIÕES"," MIL TRILIÕES"],
br: ["","MIL"," MILHÃO"," BILHÃO"," TRILHÃO"," QUADRILHÃO"," QUINTILHÃO"," SEXTILHÃO",""," MIL"," MILHÕES"," BILHÕES"," TRILHÕES"," QUADRILHÕES"," QUINTILHÕES"," SEXTILHÕES"]}
- # Produz a moeda e o extenso da parte fracionária do valor monetário em portugûes de portugal ou brasil.
- #
- # @param [Integer] fracao parte fracionária do valor monetário ex: 100022.12 = 12
- # @return [String] a moeda e o extenso da parte fracionária do valor monetário
- def self.efracao(fracao)
- inteira=@@ai.find{|v|v>0}.to_i+@@ai[1..-1].to_a.find{|v|v>0}.to_i
- total=inteira+fracao
- (@@ai[2..-1].to_a.find{|v|v>0}.to_i>0&&@@ai[0..1].inject(:+).to_i==0?" DE":@@ai.count>0&&total==0?"ZERO "+@@mp:"")+
- (inteira>0?inteira>1?" "+@@mp:" "+@@ms:"")+
- (inteira>0&&fracao>0?" E ":"")+e999(fracao)+
- (fracao>0?fracao>1?" "+@@cp:" "+@@cs:"")
- end
-
# Produz o extenso dum grupo de 3 digitos em portugûes de portugal ou brasil.
#
# @param [Integer] mil o valor dum grupo de 3 digitos a converter
# @param [Integer] pos posição deste grupo de 3 digitos no valor monetário em tratamento
- # @return [String] o extenso de <mil>
+ # @return [String] o extenso dum grupo de 3 digitos
def self.e999(mil,pos=0)
cem=mil%100
- A1000[@@lc][(mil>100?1:0)+mil/100]+(mil>100&&mil%100>0?" E ":"")+
- A0100[@@lc][cem/10]+(mil>20&&mil%10>0?" E ":"")+
- A0020[@@lc][pos==1&&mil==1?0:cem<20?cem:cem%10]
+ A1000[@@lc][(mil>100?1:0)+mil/100]+(mil>100&&cem>0?" E ":"")+ # extenso das centenas
+ A0100[@@lc][cem/10]+(mil>20&&mil%10>0?" E ":"")+ # extenso dos dezenas
+ A0020[@@lc][pos==1&&mil==1?0:cem<20?cem:cem%10] # extenso das unidades mais 10-19
end
- # Produz o extenso da parte inteira do valor monetário em portugûes de portugal ou brasil.
+ # Produz o extenso dum valor monetário em portugûes de portugal ou brasil.
#
- # @param [Integer] pos posição actual nos grupos de 3 digitos do valor monetário em tratamento
- # @param [String] ext extenso actual em tratamento
- # @return [String] o extenso da parte inteira do valor monetário
- def self.einteira(pos=0,ext="")
+ # @param [Integer] pos posição actual nos grupos de 3 digitos do valor monetário
+ # @param [String] ext extenso actual em construção
+ # @return [String] o extenso dum valor monetário
+ def self.enumerico(pos=0,ext="")
+
+ # testa fim do valor monetário
if (pos>=@@ai.count)
- ext
+
+ # soma os grupos de 3 digitos para controle de singular/plural
+ so1=@@ai[0].to_i+@@ai[1].to_i*2 # primeiros dois grupos
+ so2=@@ai[2..-1].to_a.inject(:+).to_i*2 # restantes grupos
+
+ if (so1+so2+@@nf==0)
+ "ZERO "+@@mp # caso especial de zero
+ else
+ ext+=" DE" if (so2>0&&so1==0) # proposição DE para valores >1e6 mas 0 nos primeiros 6 digitos
+ ext+=" "+@@ms if (so1+so2==1) # singular da moeda
+ ext+=" "+@@mp if (so1+so2>1) # plural da moeda
+ ext+=" E " if (so1+so2>0&&@@nf>0) # proposição E entre parte inteira e parte fracionária
+ ext+=e999(@@nf) # extenso da parte fracionária
+ ext+=" "+@@cs if (@@nf==1) # singular da parte fracionária
+ ext+=" "+@@cp if (@@nf>1) # plural da parte fracionária
+ ext
+ end
else
- ctl=pos>0?@@ai[pos-1]:0
- ext=e999(@@ai[pos],pos)+A1e24[@@lc][@@ai[pos]>0?@@ai[pos]>1?8+pos:pos:0]+(ctl>100?" ":ctl>0?" E ":"")+ext
- einteira(pos+1,ext)
+ # extenso do grupo actual de 3 digitos
+ dg3 =e999(@@ai[pos],pos)
+ dg3+=A1e24[@@lc][@@ai[pos]>0?@@ai[pos]>1?8+pos:pos:0] # qualificador do grupo actual
+ dg3+=pos>0?@@ai[pos-1]>100?" ":@@ai[pos-1]>0?" E ":"":"" # separação entre grupo actual e anterior
+
+ # proximo grupo de 3 digitos
+ enumerico(pos+1,dg3+ext)
end
end
- # Converte um objeto no seu extenso em portugûes de portugal ou brasil.
+ # Converte um objeto criando extenso(s) em portugûes de portugal ou brasil.
#
- # @param [Hash] moeda as opcoes para parametrizar a moeda/fração
- # @option moeda [Symbol] :lc locale do extenso - portugûes de portugal (:pt) ou brasil (:br)
- # @option moeda [String] :msingular Moeda no singular - pode ser inferido do <b>:mplural menos "S"</b>
- # @option moeda [String] :fsingular Fração no singular - pode ser inferido do <b>:fplural menos "S"</b>
- # @option moeda [String] :mplural Moeda no plural - pode ser inferido do <b>:msingular+"S"</b>
- # @option moeda [String] :fplural Fração no plural - pode ser inferido do <b>:fsingular+"S"</b>
+ # @param [Object] objeto o objeto a converter pode ser (String, Float, Integer, Array, Range, Hash) ou uma mistura
# @return [String, Array<String>, Hash<String>] extenso se o objecto for (String, Float, Integer), Array dos extensos se o objecto for (Array, Range) ou Hash dos extensos se o objecto for (Hash)
- def extenso(moeda={lc:(:pt),msingular:"EURO",fsingular:"CÊNTIMO"})
- # parametrização da moeda
- moeda={lc:(:br),msingular:"REAL",mplural:"REAIS",fsingular:"CENTAVO"} if (moeda[:lc]==:br&&!moeda[:mplural]&&!moeda[:fplural])
- @@lc=LC.include?(moeda[:lc])?moeda[:lc]:(:pt)
- @@ms=moeda[:msingular]?moeda[:msingular]:moeda[:mplural].to_s[-1]=="S"?moeda[:mplural][0..-2]:"EURO"
- @@cs=moeda[:fsingular]?moeda[:fsingular]:moeda[:fplural].to_s[-1]=="S"?moeda[:fplural][0..-2]:"CÊNTIMO"
- @@mp=moeda[:mplural]?moeda[:mplural]:@@ms+"S"
- @@cp=moeda[:fplural]?moeda[:fplural]:@@cs+"S"
- if (self.kind_of?Hash)
+ def self.eobjeto(obj)
+
+ if (obj.kind_of?Hash)
# converte os valores do Hash nos seus extensos mantendo as chaves - devolve um Hash
- self.map{|k,v|[k,v.extenso(lc:(@@lc),msingular:@@ms,fsingular:@@cs,mplural:@@mp,fplural:@@cp)]}.to_h
- elsif (self.respond_to?:to_a)
- # converte o objecto num Array e converte os valores nos seus extensos - devolve um Array
- self.to_a.map{|a|a.extenso(lc:(@@lc),msingular:@@ms,fsingular:@@cs,mplural:@@mp,fplural:@@cp)}
+ obj.map{|k,v|[k,eobjeto(v)]}.to_h
+ elsif (obj.respond_to?:to_a)
+ # converte o objecto num Array e converte os valores do Array nos seus extensos - devolve um Array
+ obj.to_a.map{|a|eobjeto(a)}
else
- # converter com bigdecimal/util para evitar bugs com valores superiores a 1e12
- n=self.to_d.to_s('F')
- # dividir parte inteira em grupos de 3 digitos ex: 123022.12 => [22, 123]
- @@ai=n[/^\d+/].to_s.reverse.scan(/\d{1,3}/).map{|i|i.reverse.to_i}
+ # converte objeto numa string de digitos usando bigdecimal/util para evitar bugs com valores superiores a 1e12
+ # qualquer valor não convertivel (ex: texto) resulta em "0.0"
+ svalor=obj.to_d.to_s('F')
+
+ # array da parte inteira do valor monetário dividido em grupos de 3 digitos ex: 123022.12 => [22, 123]
+ @@ai=svalor[/^\d+/].to_s.reverse.scan(/\d{1,3}/).map{|i|i.reverse.to_i}
+
+ # parte fracionária do valor monetário ex: 123022.12 => 12
+ # arredondada a 2 casas decimais (cêntimos/centavos)
+ @@nf=(svalor[/\.\d*/].to_f*100).round
+
+ # valores superiores a 1e24 não são tratados
if (@@ai.count>8)
- "" # MAX 1e24
+ ""
else
- ExtensoPt.einteira+
- # parte fracionária é arredondada a 2 casas decimais (cêntimos)
- ExtensoPt.efracao((n[/\.\d*/].to_f*100).round)
+ # extenso num numerico
+ enumerico
end
end
end
+ # Produz extenso(s) de objeto(s) em portugûes de portugal ou brasil.
+ #
+ # @param [Hash] moeda as opcoes para parametrizar a moeda/fração
+ # @option moeda [Symbol] :lc locale do extenso - portugûes de portugal (:pt) ou brasil (:br)
+ # @option moeda [String] :msingular moeda no singular - pode ser inferido do plural menos "S"
+ # @option moeda [String] :fsingular fração no singular - pode ser inferido do plural menos "S"
+ # @option moeda [String] :mplural moeda no plural - pode ser inferido do singular mais "S"
+ # @option moeda [String] :fplural fração no plural - pode ser inferido do singular mais "S"
+ # @return [String, Array<String>, Hash<String>] extenso se o objecto for (String, Float, Integer), Array dos extensos se o objecto for (Array, Range) ou Hash dos extensos se o objecto for (Hash)
+ def extenso(moeda={lc:(:pt),msingular:"EURO",fsingular:"CÊNTIMO"})
+
+ # parametrização por defeito para locale => :br
+ if (moeda[:lc]==:br&&!moeda[:mplural]&&!moeda[:fplural])
+ moeda={lc:(:br),msingular:"REAL",mplural:"REAIS",fsingular:"CENTAVO"}
+ end
+
+ # se locale nao for [:pt,:br] entao :pt
+ if (LC.include?moeda[:lc])
+ @@lc=moeda[:lc]
+ else
+ @@lc=:pt
+ end
+
+ # inferir singular da moeda a partir do plural
+ if (moeda[:msingular])
+ @@ms=moeda[:msingular]
+ elsif (moeda[:mplural].to_s[-1]=="S")
+ @@ms=moeda[:mplural][0..-2]
+ else
+ @@ms="EURO"
+ end
+ # inferir singular da fração a partir do plural
+ if (moeda[:fsingular])
+ @@cs=moeda[:fsingular]
+ elsif (moeda[:fplural].to_s[-1]=="S")
+ @@cs=moeda[:fplural][0..-2]
+ else
+ @@cs="CÊNTIMO"
+ end
+
+ # inferir plural da moeda a partir do singular
+ if (moeda[:mplural])
+ @@mp=moeda[:mplural]
+ else
+ @@mp=@@ms+"S"
+ end
+ # inferir plural da fração a partir do singular
+ if (moeda[:fplural])
+ @@cp=moeda[:fplural]
+ else
+ @@cp=@@cs+"S"
+ end
+
+ # extenso do objeto
+ ExtensoPt.eobjeto(self)
+ end
end
class Hash; include ExtensoPt;end
class Array; include ExtensoPt;end
class Range; include ExtensoPt;end
class Float; include ExtensoPt;end