Module: ExtensoPt

Included in:
Array, Hash, Numeric, Range, String
Defined in:
lib/extenso_pt.rb,
lib/extenso_pt/romana.rb,
lib/extenso_pt/extenso.rb,
lib/extenso_pt/version.rb

Constant Summary collapse

RO_RE =

expressao regular da numeracao romana

/^M*(D?C{0,3}|C[DM])(L?X{0,3}|X[LC])(V?I{0,3}|I[VX])$/i.freeze
MOEDA =

chaves parametrizacao moeda permitidas

%i[moeda_singular fracao_singular moeda_plural fracao_plural lc].freeze
EXTLC =

somente portugues de portugal ou brasil permitidos, qualquer outro locale equivale usar :pt

%i[pt br].freeze
ROMAN =

numeracao romana ordem decrescente (ordem importante)

{ M: 1000, CM: 900, D: 500, CD: 400, C: 100, XC: 90, L: 50, XL: 40, X: 10, IX: 9, V: 5, IV: 4, I: 1 }.freeze
A0020 =
{ pt: ['']     + e013a + ['CATORZE'] + e019a, br: ['']     + e013a + ['QUATORZE'] + e019a }.freeze
A0100 =
{ pt: ['', ''] + e090a,                       br: ['', ''] + e090a                        }.freeze
A1000 =
{ pt: ['']     + e900a,                       br: ['']     + e900a                        }.freeze
S1E24 =
Note:

escala segundo convencao entre varios paises, na 9a Conferencia Geral de Pesos e Medidas (12-21 de Outubro de 1948), organizada pelo Bureau International des Poids et Mesures

singular extensos 1e3 ate 1e24

Examples:

1 000 000 = milhao
1 000 000 000 000 = biliao
1 000 000 000 000 000 000 = triliao
1 000 000 000 000 000 000 000 000 = quadriliao
1 000 000 000 000 000 000 000 000 000 000 = quintiliao
1 000 000 000 000 000 000 000 000 000 000 000 000 = sextiliao
{
  pt: ['', 'MIL', ' MILHÃO', ' MIL MILHÃO', ' BILIÃO', ' MIL BILIÃO', ' TRILIÃO', ' MIL TRILIÃO'],
  br: ['', 'MIL', ' MILHÃO', ' BILHÃO', ' TRILHÃO', ' QUADRILHÃO', ' QUINTILHÃO', ' SEXTILHÃO']
}.freeze
P1E24 =
Note:

escala segundo convencao entre varios paises, na 9a Conferencia Geral de Pesos e Medidas (12-21 de Outubro de 1948), organizada pelo Bureau International des Poids et Mesures

plural extensos 1e3 ate 1e24

{
  pt: ['', ' MIL', ' MILHÕES', ' MIL MILHÕES', ' BILIÕES', ' MIL BILIÕES', ' TRILIÕES', ' MIL TRILIÕES'],
  br: ['', ' MIL', ' MILHÕES', ' BILHÕES', ' TRILHÕES', ' QUADRILHÕES', ' QUINTILHÕES', ' SEXTILHÕES']
}.freeze
VERSION =
'0.8.1'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.centenas(mil) ⇒ String

Returns extenso das centenas em portugues de portugal ou brasil.

Parameters:

  • mil (Integer)

    o valor dum grupo 3 digitos a converter

Returns:

  • (String)

    extenso das centenas em portugues de portugal ou brasil



85
86
87
88
# File 'lib/extenso_pt/extenso.rb', line 85

def self.centenas(mil)
  cem = mil > 100
  A1000[@lc][(cem ? 1 : 0) + mil / 100] + (cem && (mil % 100).positive? ? ' E ' : '')
end

.dezenas(cem) ⇒ String

Returns extenso das dezenas em portugues de portugal ou brasil.

Parameters:

  • cem (Integer)

    a centena dum grupo 3 digitos a converter

Returns:

  • (String)

    extenso das dezenas em portugues de portugal ou brasil



92
93
94
# File 'lib/extenso_pt/extenso.rb', line 92

def self.dezenas(cem)
  A0100[@lc][cem / 10] + (cem > 20 && (cem % 10).positive? ? ' E ' : '')
end

.extenso_completo(pos = 0, ext = '') ⇒ String

Returns extenso do valor monetario completo.

Parameters:

  • pos (Integer) (defaults to: 0)

    posicao no grupo 3 digitos

  • ext (String) (defaults to: '')

    extenso em construcao

Returns:

  • (String)

    extenso do valor monetario completo



161
162
163
164
165
166
167
168
169
170
# File 'lib/extenso_pt/extenso.rb', line 161

def self.extenso_completo(pos = 0, ext = '')
  # testa fim do valor monetario
  if pos >= @ai.count
    # caso especial de zero
    (soma_grupos + @nf).zero? ? "ZERO #{@mp}" : "#{ext}#{final}"
  else
    # converte grupo 3 digitos na posicao corrente & envoca proxima posicao
    extenso_completo(pos + 1, extenso_grupo(pos) + ext)
  end
end

.extenso_grupo(pos) ⇒ String

Returns extenso do grupo 3 digitos em portugues de portugal ou brasil.

Parameters:

  • pos (Integer)

    posicao actual nos grupos 3 digitos

Returns:

  • (String)

    extenso do grupo 3 digitos em portugues de portugal ou brasil



146
147
148
149
150
151
152
153
154
155
156
# File 'lib/extenso_pt/extenso.rb', line 146

def self.extenso_grupo(pos)
  grp = @ai[pos]
  dez = grp % 100
  # caso especial MIL EUROS
  if pos == 1 && grp == 1
    ''
  else
    # extenso das centenas + extenso das dezenas + extenso das unidades
    "#{centenas(grp)}#{dezenas(dez)}#{unidades(dez)}"
  end + qualificador_grupo(pos)
end

.finalString

Returns final da moeda em portugues de portugal ou brasil.

Returns:

  • (String)

    final da moeda em portugues de portugal ou brasil



112
113
114
115
116
117
118
119
120
# File 'lib/extenso_pt/extenso.rb', line 112

def self.final
  som = soma_grupos
  if som.positive?
    # proposicao DE entre parte inteira e moeda & moeda singular/plural
    "#{testa_de? ? ' DE ' : ' '}#{som > 1 ? @mp : @ms}"
  else
    ''
  end + fracionaria
end

.fracionariaString

Returns proposicao E & extenso da parte fracionaria em portugues de portugal ou brasil.

Returns:

  • (String)

    proposicao E & extenso da parte fracionaria em portugues de portugal ou brasil



103
104
105
106
107
108
109
# File 'lib/extenso_pt/extenso.rb', line 103

def self.fracionaria
  if @nf.positive?
    "#{soma_grupos.positive? ? ' E ' : ''}#{dezenas(@nf)}#{unidades(@nf)} #{@nf > 1 ? @fp : @fs}"
  else
    ''
  end
end

.gruposArray<Integer>

Returns grupos 3 digitos da parte inteira.

Returns:

  • (Array<Integer>)

    grupos 3 digitos da parte inteira



69
70
71
# File 'lib/extenso_pt/extenso.rb', line 69

def self.grupos
  @ai
end

.parametrizar_grupos(digitos) ⇒ Object

Parametrizar variaveis parte inteira e fracionaria

Parameters:

  • digitos (String)

    do valor monetario a converter



60
61
62
63
64
65
66
# File 'lib/extenso_pt/extenso.rb', line 60

def self.parametrizar_grupos(digitos)
  # cria array de grupos 3 digitos da parte inteira ex: 123022.12 => [22, 123]
  @ai = digitos[/^\d+/].reverse.scan(/\d{1,3}/).map { |grp| Integer(grp.reverse) }

  # obtem parte fracionaria da string digitos arredondada a 2 casas decimais ex: 123022.124 => 12, 123022.125 => 13
  @nf = (Float(digitos[/\.\d*/]) * 100).round
end

.parametrizar_moeda(moeda) ⇒ Object

Parametrizar variaveis da moeda

Parameters:

  • moeda (Hash<String, Symbol>)

    opcoes parametrizar moeda/fracao

Options Hash (moeda):

  • :lc (Symbol)

    locale do extenso - portugues de portugal (:pt) portugues do brasil (:br)

  • :moeda_singular (String)

    moeda no singular

  • :fracao_singular (String)

    fracao no singular

  • :moeda_plural (String)

    moeda no plural

  • :fracao_plural (String)

    fracao no plural



47
48
49
50
51
52
53
54
55
# File 'lib/extenso_pt/extenso.rb', line 47

def self.parametrizar_moeda(moeda)
  # parametrizacao por defeito
  # the first mention of a @<variable> creates that instance variable in the current object ie: self = ExtensoPt
  @lc = moeda[:lc] || :pt
  @ms = moeda[:moeda_singular] || 'EURO'
  @fs = moeda[:fracao_singular] || 'CÊNTIMO'
  @mp = moeda[:moeda_plural] || "#{@ms}S"
  @fp = moeda[:fracao_plural] || "#{@fs}S"
end

.proposicao_grupo(pos) ⇒ String

Returns proposicao E entre grupos 3 digitos.

Parameters:

  • pos (Integer)

    posicao actual nos grupos 3 digitos

Returns:

  • (String)

    proposicao E entre grupos 3 digitos



124
125
126
127
128
129
130
131
# File 'lib/extenso_pt/extenso.rb', line 124

def self.proposicao_grupo(pos)
  grp = @ai[pos - 1]
  if pos.positive? && grp.positive?
    grp > 100 ? ' ' : ' E '
  else
    ''
  end
end

.qualificador_grupo(pos) ⇒ String

Returns qualificador grupo de 3 digitos em portugues de portugal ou brasil.

Parameters:

  • pos (Integer)

    posicao actual nos grupos 3 digitos

Returns:

  • (String)

    qualificador grupo de 3 digitos em portugues de portugal ou brasil



135
136
137
138
139
140
141
142
# File 'lib/extenso_pt/extenso.rb', line 135

def self.qualificador_grupo(pos)
  grp = @ai[pos]
  if grp.positive?
    grp > 1 ? P1E24[@lc][pos] : S1E24[@lc][pos]
  else
    ''
  end + proposicao_grupo(pos)
end

.ri2r(inteiro) ⇒ String

Returns numeral romano do inteiro.

Parameters:

  • inteiro (Integer)

    a converter

Returns:

  • (String)

    numeral romano do inteiro



10
11
12
13
14
# File 'lib/extenso_pt/romana.rb', line 10

def self.ri2r(inteiro)
  return '' if inteiro.zero?

  ROMAN.each { |srm, val| return "#{srm}#{ri2r(inteiro - val)}" if val <= inteiro }
end

.rr2i(numeral, ultimo) ⇒ Integer

Returns inteiro do numeral romano.

Parameters:

  • numeral (String)

    romano a converter

  • ultimo (Integer)

    valor convertido

Returns:

  • (Integer)

    inteiro do numeral romano



19
20
21
22
23
24
# File 'lib/extenso_pt/romana.rb', line 19

def self.rr2i(numeral, ultimo)
  return 0 if numeral.empty?

  val = ROMAN[numeral[-1].to_sym]
  rr2i(numeral.chop, val) + (val < ultimo ? -val : val)
end

.soma_gruposInteger

Returns soma grupos 1-8 de digitos.

Returns:

  • (Integer)

    soma grupos 1-8 de digitos



74
75
76
# File 'lib/extenso_pt/extenso.rb', line 74

def self.soma_grupos
  Integer(@ai[0]) + Integer(@ai[1] || 0) * 2 + Integer(@ai[2..].to_a.inject(:+) || 0) * 2
end

.testa_de?true, false

Returns sim ou nao proposicao DE.

Returns:

  • (true, false)

    sim ou nao proposicao DE



79
80
81
# File 'lib/extenso_pt/extenso.rb', line 79

def self.testa_de?
  Integer(@ai[0..1].inject(:+)).zero? && Integer(@ai[2..].to_a.inject(:+) || 0).positive?
end

.unidades(cem) ⇒ String

Returns extenso das unidades em portugues de portugal ou brasil.

Parameters:

  • cem (Integer)

    a centena dum grupo 3 digitos a converter

Returns:

  • (String)

    extenso das unidades em portugues de portugal ou brasil



98
99
100
# File 'lib/extenso_pt/extenso.rb', line 98

def self.unidades(cem)
  A0020[@lc][cem < 20 ? cem : cem % 10]
end

Instance Method Details

#eliminar_erradosHash<String, Symbol>

Returns parametrizacao moeda eliminar parametros errados.

Returns:

  • (Hash<String, Symbol>)

    parametrizacao moeda eliminar parametros errados



56
57
58
# File 'lib/extenso_pt.rb', line 56

def eliminar_errados
  keep_if { |key, val| MOEDA.include?(key) && (key != :lc || EXTLC.include?(val)) }
end

#extenso(moeda = { lc: :pt }) ⇒ String, ...

Note:

valor numerico pode ser uma string digitos

Processa objeto criando extenso(s) em portugues de portugal ou brasil

Parameters:

  • moeda (Hash<String, Symbol>) (defaults to: { lc: :pt })

    opcoes parametrizar moeda/fracao

Options Hash (moeda):

  • :lc (Symbol)

    locale do extenso - portugues de portugal (:pt) portugues do brasil (:br)

  • :moeda_singular (String)

    moeda no singular

  • :fracao_singular (String)

    fracao no singular

  • :moeda_plural (String)

    moeda no plural

  • :fracao_plural (String)

    fracao no plural

Returns:

  • (String, Array<String>, Hash<String>)

    String<extenso> se objecto for (String, Float, Integer), Array<extensos> se objecto for (Array, Range), Hash<extensos> se objecto for (Hash)



30
31
32
33
34
35
# File 'lib/extenso_pt.rb', line 30

def extenso(moeda = { lc: :pt })
  # parametrizar moeda
  ExtensoPt.parametrizar_moeda(moeda.parametrizar)

  processa
end

#inferir_singularHash<String, Symbol>

Returns parametrizacao moeda singular inferindo do plural.

Returns:

  • (Hash<String, Symbol>)

    parametrizacao moeda singular inferindo do plural



47
48
49
50
51
52
53
# File 'lib/extenso_pt.rb', line 47

def inferir_singular
  mdp = fetch(:moeda_plural, '')
  frp = fetch(:fracao_plural, '')
  self[:moeda_singular] ||= (mdp[0..-2] if mdp[-1] == 'S')
  self[:fracao_singular] ||= (frp[0..-2] if frp[-1] == 'S')
  self
end

#parametrizarHash<String, Symbol>

Returns parametrizacao moeda por defeito para :br & inferencias & errados.

Returns:

  • (Hash<String, Symbol>)

    parametrizacao moeda por defeito para :br & inferencias & errados



38
39
40
41
42
43
44
# File 'lib/extenso_pt.rb', line 38

def parametrizar
  if value?(:br) && %i[moeda_singular moeda_plural].all? { |syb| !keys.include?(syb) }
    { lc: :br, moeda_singular: 'REAL', moeda_plural: 'REAIS', fracao_singular: 'CENTAVO', fracao_plural: 'CENTAVOS' }
  else
    inferir_singular.eliminar_errados
  end
end

#processaString, ...

Returns String<extenso> se objecto for (String, Float, Integer), Array<extensos> se objecto for (Array, Range), Hash<extensos> se objecto for (Hash).

Returns:

  • (String, Array<String>, Hash<String>)

    String<extenso> se objecto for (String, Float, Integer), Array<extensos> se objecto for (Array, Range), Hash<extensos> se objecto for (Hash)



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/extenso_pt.rb', line 61

def processa
  # converte num Array com os valores convertidos nos seus extensos
  return to_a.map(&:processa) if is_a?(Range) || is_a?(Array)
  # converte valores do Hash nos seus extensos
  return transform_values(&:processa) if is_a?(Hash)

  # converte objeto em string digitos utilizando bigdecimal para
  #  evitar problemas com aritmetica virgula flutuante em valores >1e12
  #  valores negativos sao convertidos em positivos
  # parametrizar parte inteira/fracionaria (@ai, @nf) da string digitos
  ExtensoPt.parametrizar_grupos(to_d.abs.to_s('F'))

  # processar extenso - valores >= 1e24 sao ignorados
  ExtensoPt.grupos.count > 8 ? '' : ExtensoPt.extenso_completo
end

#romanaString, Integer

Note:

valor numerico pode ser uma string digitos

Returns numeracao romana a partir de numerico ou inteiro a partir da numeracao romana.

Returns:

  • (String, Integer)

    numeracao romana a partir de numerico ou inteiro a partir da numeracao romana



79
80
81
82
83
84
85
86
# File 'lib/extenso_pt.rb', line 79

def romana
  # converte num Array com os valores convertidos
  return to_a.map(&:romana) if is_a?(Range) || is_a?(Array)
  # converte os valores do Hash
  return transform_values(&:romana) if is_a?(Hash)

  romana_base(to_i.abs)
end

#romana?true, false

Returns testa se contem numeracao romana.

Returns:

  • (true, false)

    testa se contem numeracao romana



98
99
100
# File 'lib/extenso_pt.rb', line 98

def romana?
  is_a?(String) ? RO_RE.match?(upcase) : false
end

#romana_base(inteiro) ⇒ String, Integer

Returns numeracao romana a partir de numerico ou inteiro a partir da numeracao romana.

Returns:

  • (String, Integer)

    numeracao romana a partir de numerico ou inteiro a partir da numeracao romana



89
90
91
92
93
94
95
# File 'lib/extenso_pt.rb', line 89

def romana_base(inteiro)
  # numeracao romana a partir de inteiro ou string digitos (ignora parte fracionaria & negativos)
  return ExtensoPt.ri2r(inteiro) unless inteiro.zero?

  # inteiro a partir da numeracao romana
  RO_RE.match?(to_s) ? ExtensoPt.rr2i(upcase, 0) : ''
end