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

Overview

Author:

  • Hernani Rodrigues Vaz

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.6'

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 se objecto for (String, Float, Integer), Array se objecto for (Array, Range), Hash 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 se objecto for (String, Float, Integer), Array se objecto for (Array, Range), Hash se objecto for (Hash).

Returns:

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

    String se objecto for (String, Float, Integer), Array se objecto for (Array, Range), Hash 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