extenso_pt 0.5.7 → 0.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9801fcabf1093be0b72526b73018bc35a4ba41dcd7ed605a56a47096cf8b30a6
4
- data.tar.gz: e8e1a1103571ebc158c1c915d0146d9727e29f46d77418300dbcf42e01e9fe8e
3
+ metadata.gz: 957540b2bccdc61b30b6c221465b11573c9570720729dafd3df982ab73216da1
4
+ data.tar.gz: 4f2159763f75b938535d61c293834f0f039395d577521d7d8d56cbe19592fe42
5
5
  SHA512:
6
- metadata.gz: b69172bc248e90890a9c5ac2283e30b3d63208d0553ec6f95535f844aacd98f0d82fba7e2fbf779d3d7ed386e5170b085dc2f91cd518b58e3a40ca664ce991b0
7
- data.tar.gz: afda6adfd8b283323fd801344659fdf2238bf273d080d1d710b2b2169e3cd9ebc0bdc358b1baf0e53e5a5657090e77abe29e3aefb5d78e19065cb39aeeae0ae9
6
+ metadata.gz: ec98f28a4969f2ed153086b55b781b89c617276d4d16bbb3de600dfa765b083a7ee6abd832a0f7d44eb13f7801deb189e1f7dc2890210934dbf5b27f09a79175
7
+ data.tar.gz: af1f863cad4cbce9c8aeaceb0353ccc2518ca7155428fa5fb4554fc095eecacae9222e1337cb7261462900b0f383dfd2cc1fa9c4ea913daf9bc9ad77a85022ed
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- extenso_pt (0.5.7)
4
+ extenso_pt (0.5.8)
5
+ bigdecimal (~> 1.4.4)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
@@ -14,7 +15,6 @@ PLATFORMS
14
15
  ruby
15
16
 
16
17
  DEPENDENCIES
17
- bigdecimal (~> 1.4.4)
18
18
  bundler (~> 1.17)
19
19
  extenso_pt!
20
20
  minitest (~> 5.0)
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ExtensoPt [![Build Status](https://travis-ci.org/hernanilr/extenso_pt.svg?branch=master)](https://travis-ci.org/hernanilr/extenso_pt)
2
2
 
3
- Produz valores monetários por extenso em portugês de portugal ou brasil. Os valores podem ser um numerico, uma string de digitos ou um conjunto destes (array, range, hash). O extenso pode ser produzido na escala longa (utilizada em todos os países lusófonos) ou na escala curta (utilizada no Brasil) [wiki](https://pt.wikipedia.org/wiki/Escalas_curta_e_longa). Pode ainda escolher a moeda e a fração da moeda.
3
+ Converte valores monetários em extenso de portugês de portugal, brasil ou numeracao romana. Os valores podem ser um numerico, uma string de digitos ou um conjunto destes (array, range, hash). O extenso pode ser produzido na escala longa (utilizada em todos os países lusófonos) ou na escala curta (utilizada no Brasil) [wiki](https://pt.wikipedia.org/wiki/Escalas_curta_e_longa). Pode ainda converter os valores em numeracao romana e vice versa.
4
4
 
5
5
  ## Installation
6
6
 
@@ -21,7 +21,9 @@ Or install it yourself as:
21
21
  ## Usage
22
22
 
23
23
  ```ruby
24
- "1234".extenso => "MIL DUZENTOS E TRINTA E QUATRO EUROS"
24
+ 1234.extenso => "MIL DUZENTOS E TRINTA E QUATRO EUROS"
25
+ 1234.romana => "MCCXXXIV"
26
+ "MCCXXXIV".romana => 1234
25
27
  12000000.12.extenso => "DOZE MILHÕES DE EUROS E DOZE CÊNTIMOS"
26
28
  1.01.extenso(msingular:"DÓLAR") => "UM DÓLAR E UM CÊNTIMO"
27
29
  10.1.extenso(mplural:"DÓLARES") => "DEZ DÓLARES E DEZ CÊNTIMOS" # plural inferido <silgular> mais "S"
data/extenso_pt.gemspec CHANGED
@@ -12,14 +12,14 @@ Gem::Specification.new do |spec|
12
12
  spec.homepage = 'https://github.com/hernanilr/extenso_pt'
13
13
  spec.license = 'MIT'
14
14
 
15
- spec.summary = 'Produz valores monetários por extenso '\
16
- 'em portugês de portugal ou brasil.'
17
-
18
- spec.description = spec.summary + ' Os valores podem ser um numerico, uma '\
19
- 'string de digitos ou um conjunto destes (array, range, hash). O extenso '\
20
- 'pode ser produzido na escala longa (utilizada em todos os países '\
21
- 'lusófonos) ou na escala curta (utilizada no Brasil). Pode ainda escolher '\
22
- 'a moeda e a fração da moeda.'
15
+ spec.summary = 'Converte valores monetários em extenso de portugês de ' \
16
+ 'portugal, brasil ou numeracao romana.'
17
+ spec.description = spec.summary
18
+ spec.description += ' Os valores podem ser um numerico, uma string ' \
19
+ 'de digitos ou um conjunto destes (array, range, hash). O extenso ' \
20
+ 'pode ser produzido na escala longa (utilizada em todos os países ' \
21
+ 'lusófonos) ou na escala curta (utilizada no Brasil). Pode ainda ' \
22
+ 'converter os valores em numeracao romana e vice versa.'
23
23
 
24
24
  spec.metadata['yard.run'] = 'yard' # use "yard" to build full HTML docs.
25
25
  spec.metadata['homepage_uri'] = spec.homepage
@@ -34,8 +34,9 @@ Gem::Specification.new do |spec|
34
34
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
35
  spec.require_paths = ['lib']
36
36
 
37
- spec.add_development_dependency 'bigdecimal', '~> 1.4.4'
38
37
  spec.add_development_dependency 'bundler', '~> 1.17'
39
38
  spec.add_development_dependency 'minitest', '~> 5.0'
40
39
  spec.add_development_dependency 'rake', '~> 10.0'
40
+
41
+ spec.add_dependency 'bigdecimal', '~> 1.4.4'
41
42
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @author Hernani Rodrigues Vaz
4
+ module ExtensoPt
5
+ # constantes para producao de extenso em portugues de portugal ou brasil
6
+ EXTLC = %i[pt br].freeze
7
+ A0020 = {
8
+ pt: ['', 'UM', 'DOIS', 'TRÊS', 'QUATRO', 'CINCO', 'SEIS', 'SETE',
9
+ 'OITO', 'NOVE', 'DEZ', 'ONZE', 'DOZE', 'TREZE', 'CATORZE',
10
+ 'QUINZE', 'DEZASSEIS', 'DEZASSETE', 'DEZOITO', 'DEZANOVE'],
11
+ br: ['', 'UM', 'DOIS', 'TRES', 'QUATRO', 'CINCO', 'SEIS', 'SETE',
12
+ 'OITO', 'NOVE', 'DEZ', 'ONZE', 'DOZE', 'TREZE', 'QUATORZE',
13
+ 'QUINZE', 'DEZESSEIS', 'DEZESSETE', 'DEZOITO', 'DEZENOVE']
14
+ }.freeze
15
+ A0100 = {
16
+ pt: ['', '', 'VINTE', 'TRINTA', 'QUARENTA', 'CINQUENTA', 'SESSENTA',
17
+ 'SETENTA', 'OITENTA', 'NOVENTA'],
18
+ br: ['', '', 'VINTE', 'TRINTA', 'QUARENTA', 'CINQUENTA', 'SESSENTA',
19
+ 'SETENTA', 'OITENTA', 'NOVENTA']
20
+ }.freeze
21
+ A1000 = {
22
+ pt: ['', 'CEM', 'CENTO', 'DUZENTOS', 'TREZENTOS', 'QUATROCENTOS',
23
+ 'QUINHENTOS', 'SEISCENTOS', 'SETECENTOS', 'OITOCENTOS', 'NOVECENTOS'],
24
+ br: ['', 'CEM', 'CENTO', 'DUZENTOS', 'TREZENTOS', 'QUATROCENTOS',
25
+ 'QUINHENTOS', 'SEISCENTOS', 'SETECENTOS', 'OITOCENTOS', 'NOVECENTOS']
26
+ }.freeze
27
+
28
+ # escala longa portugal segundo convencao entre varios paises,
29
+ # na 9a Conferencia Geral de Pesos e Medidas (12-21 de Outubro de 1948),
30
+ # organizada pelo Bureau International des Poids et Mesures
31
+ # 1 000 000 = milhao
32
+ # 1 000 000 000 000 = biliao
33
+ # 1 000 000 000 000 000 000 = triliao
34
+ # 1 000 000 000 000 000 000 000 000 = quadriliao
35
+ # 1 000 000 000 000 000 000 000 000 000 000 = quintiliao
36
+ # 1 000 000 000 000 000 000 000 000 000 000 000 000 = sextiliao
37
+ S1E24 = { pt: ['', 'MIL', ' MILHÃO', ' MIL MILHÃO', ' BILIÃO',
38
+ ' MIL BILIÃO', ' TRILIÃO', ' MIL TRILIÃO'],
39
+ br: ['', 'MIL', ' MILHÃO', ' BILHÃO', ' TRILHÃO',
40
+ ' QUADRILHÃO', ' QUINTILHÃO', ' SEXTILHÃO'] }.freeze
41
+ P1E24 = { pt: ['', ' MIL', ' MILHÕES', ' MIL MILHÕES', ' BILIÕES',
42
+ ' MIL BILIÕES', ' TRILIÕES', ' MIL TRILIÕES'],
43
+ br: ['', ' MIL', ' MILHÕES', ' BILHÕES', ' TRILHÕES',
44
+ ' QUADRILHÕES', ' QUINTILHÕES', ' SEXTILHÕES'] }.freeze
45
+
46
+ # contantes para numeracao romana
47
+ ROMAN = { M: 1000, CM: 900,
48
+ D: 500, CD: 400,
49
+ C: 100, XC: 90,
50
+ L: 50, XL: 40,
51
+ X: 10, IX: 9,
52
+ V: 5, IV: 4,
53
+ I: 1 }.freeze
54
+ # numeral romano
55
+ RO_RE = /^M*(D?C{0,3}|C[DM])(L?X{0,3}|X[LC])(V?I{0,3}|I[VX])$/i.freeze
56
+ end
@@ -0,0 +1,219 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @author Hernani Rodrigues Vaz
4
+ module ExtensoPt
5
+ # Produz o extenso das centenas em portugues de portugal ou brasil
6
+ #
7
+ # @param [Integer] mil o valor dum grupo 3 digitos a converter
8
+ # @return [String] o extenso das centenas
9
+ def self.e900(mil)
10
+ A1000[@lc][(mil > 100 ? 1 : 0) + mil / 100] +
11
+ (mil > 100 && (mil % 100).positive? ? ' E ' : '') # proposicao
12
+ end
13
+
14
+ # Produz o extenso das dezenas em portugues de portugal ou brasil
15
+ #
16
+ # @param [Integer] cem o valor dum grupo 3 digitos a converter
17
+ # @return [String] o extenso das dezenas
18
+ def self.e90(cem)
19
+ A0100[@lc][cem / 10] +
20
+ (cem > 20 && (cem % 10).positive? ? ' E ' : '') # proposicao
21
+ end
22
+
23
+ # Produz o extenso das unidades em portugues de portugal ou brasil
24
+ #
25
+ # @param [Integer] cem o valor dum grupo 3 digitos a converter
26
+ # @return [String] o extenso das unidades
27
+ def self.e9(cem)
28
+ A0020[@lc][cem < 20 ? cem : cem % 10]
29
+ end
30
+
31
+ # Produz extenso parte fracionaria em portugues de portugal ou brasil
32
+ #
33
+ # @return [String] o extenso da parte fracionaria dum valor monetario
34
+ def self.ef99
35
+ # parametrizacao por defeito
36
+ @cs ||= 'CÊNTIMO'
37
+ @cp ||= @ms + 'S'
38
+
39
+ if @nf.positive?
40
+ e90(@nf) + e9(@nf) + (@nf > 1 ? ' ' + @cp : ' ' + @cs)
41
+ else
42
+ ''
43
+ end
44
+ end
45
+
46
+ # Produz final da moeda em portugues de portugal ou brasil
47
+ #
48
+ # @return [String] o final da moeda
49
+ def self.efim
50
+ # parametrizacao por defeito
51
+ @ms ||= 'EURO'
52
+ @mp ||= @ms + 'S'
53
+
54
+ # proposicao DE entre parte inteira e moeda
55
+ emo = @de ? ' DE' : ''
56
+ # moeda singular/plural
57
+ emo += @tt > 1 ? ' ' + @mp : ' ' + @ms if @tt.positive?
58
+ # proposicao E entre moeda e parte fracionaria
59
+ # extenso da parte fracionaria
60
+ emo + (@tt.positive? && @nf.positive? ? ' E ' : '') + ef99
61
+ end
62
+
63
+ # Produz separador entre grupos 3 digitos
64
+ #
65
+ # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
66
+ # @return [String] separador entre grupos 3 digitos
67
+ def self.esep(pos)
68
+ if pos.positive? && @ai[pos - 1].positive?
69
+ @ai[pos - 1] > 100 ? ' ' : ' E '
70
+ else
71
+ ''
72
+ end
73
+ end
74
+
75
+ # Produz qualificador grupo de 3 digitos em portugues de portugal ou brasil
76
+ #
77
+ # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
78
+ # @return [String] qualificador grupo de 3 digitos
79
+ def self.e1e24(pos)
80
+ if @ai[pos].positive?
81
+ @ai[pos] > 1 ? P1E24[@lc][pos] : S1E24[@lc][pos]
82
+ else
83
+ ''
84
+ end
85
+ end
86
+
87
+ # Produz extenso grupo 3 digitos em portugues de portugal ou brasil
88
+ #
89
+ # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
90
+ # @return [String] extenso grupo 3 digitos
91
+ def self.edg3(pos)
92
+ # parametrizacao por defeito
93
+ # the first mention of an @<variable> creates the
94
+ # instance variable in the current object ie: self = ExtensoPt
95
+ @lc ||= :pt
96
+
97
+ dg3 = if pos == 1 && @ai[pos] == 1
98
+ # caso especial MIL EUROS
99
+ ''
100
+ else
101
+ e900(@ai[pos]) + e90(@ai[pos] % 100) + e9(@ai[pos] % 100)
102
+ end
103
+ # qualificador grupo de 3 digitos
104
+ dg3 + e1e24(pos)
105
+ end
106
+
107
+ # Parametrizar controle singular/plural & proposicoes
108
+ #
109
+ # @return [void]
110
+ def self.pcontrolo
111
+ # soma grupos 1,2 (primeiros 6 digitos)
112
+ @s6 = @ai[0].to_i + @ai[1].to_i * 2
113
+ # soma grupos 3.. (digitos acima de 6)
114
+ @m6 = @ai[2..-1].to_a.inject(:+).to_i * 2
115
+ @tt = @s6 + @m6 # proposicao E & singular/plural
116
+ @de = @s6.zero? && @m6.positive? # proposicao DE
117
+ end
118
+
119
+ # Produz o extenso dum valor monetario em portugues de portugal ou brasil
120
+ #
121
+ # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
122
+ # @param [String] ext extenso em construcao
123
+ # @return [String] o extenso dum valor monetario
124
+ def self.emonetario(pos, ext)
125
+ # testa fim do valor monetario
126
+ if pos >= @ai.count
127
+ # parametrizar controle singular/plural & proposicoes
128
+ pcontrolo
129
+
130
+ # caso especial zero
131
+ (@tt + @nf).zero? ? 'ZERO ' + @mp : ext + efim
132
+ else
133
+ # tratamento do proximo grupo 3 digitos
134
+ emonetario(pos + 1, edg3(pos) + esep(pos) + ext)
135
+ end
136
+ end
137
+
138
+ # Parametrizar parte inteira/fracionaria do valor monetario
139
+ #
140
+ # @param [String] digitos do valor monetario
141
+ # @return [void]
142
+ def self.pintfra(dig)
143
+ # parte inteira do valor monetario => array grupos 3 digitos
144
+ # ex: 123022.12 => [22, 123]
145
+ @ai = dig[/^\d+/].to_s.reverse.scan(/\d{1,3}/).map { |i| i.reverse.to_i }
146
+
147
+ # parte fracionaria do valor monetario
148
+ # ex: 123022.12 => 12
149
+ # arredondada a 2 casas decimais (centimos/centavos)
150
+ @nf = (dig[/\.\d*/].to_f * 100).round
151
+ end
152
+
153
+ # Converte objeto criando extenso(s) em portugues de portugal ou brasil
154
+ #
155
+ # @param [Object] obj objeto a converter
156
+ # (String, Float, Integer, Array, Range, Hash)
157
+ # @return [String, Array, Hash] string extenso
158
+ # se objecto for (String, Float, Integer),
159
+ # array<extensos> se objecto for (Array, Range),
160
+ # hash<extensos> se objecto for (Hash)
161
+ def self.o2e(obj)
162
+ if obj.is_a?(Hash)
163
+ # converte os valores do Hash nos seus extensos - devolve um Hash
164
+ obj.map { |k, v| [k, o2e(v)] }.to_h
165
+ elsif obj.respond_to?(:to_a)
166
+ # converte o objecto num Array com os extensos dos valores
167
+ obj.to_a.map { |a| o2e(a) }
168
+ else
169
+ # converte objeto em string digitos utilizando bigdecimal para
170
+ # evitar problemas com aritmetica virgula flutuante em valores >1e12
171
+ digitos = obj.to_d.to_s('F')
172
+
173
+ # parametrizar parte inteira/fracionaria (@ai, @nf) do valor monetario
174
+ pintfra(digitos)
175
+
176
+ # processar extenso - valores superiores a 1e24 nao sao tratados
177
+ digitos[/^\d+/].length <= 24 ? emonetario(0, '') : ''
178
+ end
179
+ end
180
+
181
+ # Parametrizar moeda inferindo singular a partir do plural
182
+ #
183
+ # @param [Hash] moeda as opcoes para parametrizar a moeda/fracao
184
+ # @option moeda [Symbol] :lc locale do extenso -
185
+ # portugues de portugal (:pt) ou brasil (:br)
186
+ # @option moeda [String] :msingular moeda no singular -
187
+ # inferido do plural menos"S"
188
+ # @option moeda [String] :fsingular fracao no singular -
189
+ # inferido do plural menos "S"
190
+ # @option moeda [String] :mplural moeda no plural
191
+ # @option moeda [String] :fplural fracao no plural
192
+ # @return [void]
193
+ def self.psingular(moeda)
194
+ @ms = moeda[:msingular] ||
195
+ (moeda[:mplural].to_s[-1] == 'S' ? moeda[:mplural][0..-2] : 'EURO')
196
+ @cs = moeda[:fsingular] ||
197
+ (moeda[:fplural].to_s[-1] == 'S' ? moeda[:fplural][0..-2] : 'CÊNTIMO')
198
+ end
199
+
200
+ # Parametrizar moeda inferindo plural a partir do singular
201
+ #
202
+ # @param [Hash] moeda as opcoes para parametrizar a moeda/fracao
203
+ # @option moeda [Symbol] :lc locale do extenso -
204
+ # portugues de portugal (:pt) ou brasil (:br)
205
+ # @option moeda [String] :msingular moeda no singular
206
+ # @option moeda [String] :fsingular fracao no singular
207
+ # @option moeda [String] :mplural moeda no plural -
208
+ # inferido do singular mais "S"
209
+ # @option moeda [String] :fplural fracao no plural -
210
+ # inferido do singular mais "S"
211
+ # @return [void]
212
+ def self.pplural(moeda)
213
+ # somente [:pt, :br]
214
+ @lc = EXTLC.include?(moeda[:lc]) ? moeda[:lc] : :pt
215
+
216
+ @mp = moeda[:mplural] || @ms + 'S'
217
+ @cp = moeda[:fplural] || @cs + 'S'
218
+ end
219
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ExtensoPt
4
- VERSION = '0.5.7'
4
+ VERSION = '0.5.8'
5
5
  end
data/lib/extenso_pt.rb CHANGED
@@ -1,247 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'extenso_pt/version'
4
3
  require 'bigdecimal/util'
5
-
6
- LC = %i[pt br].freeze
7
- A0020 = {
8
- pt: ['', 'UM', 'DOIS', 'TRÊS', 'QUATRO', 'CINCO', 'SEIS', 'SETE',
9
- 'OITO', 'NOVE', 'DEZ', 'ONZE', 'DOZE', 'TREZE', 'CATORZE',
10
- 'QUINZE', 'DEZASSEIS', 'DEZASSETE', 'DEZOITO', 'DEZANOVE'],
11
- br: ['', 'UM', 'DOIS', 'TRES', 'QUATRO', 'CINCO', 'SEIS', 'SETE',
12
- 'OITO', 'NOVE', 'DEZ', 'ONZE', 'DOZE', 'TREZE', 'QUATORZE',
13
- 'QUINZE', 'DEZESSEIS', 'DEZESSETE', 'DEZOITO', 'DEZENOVE']
14
- }.freeze
15
- A0100 = {
16
- pt: ['', '', 'VINTE', 'TRINTA', 'QUARENTA', 'CINQUENTA', 'SESSENTA',
17
- 'SETENTA', 'OITENTA', 'NOVENTA'],
18
- br: ['', '', 'VINTE', 'TRINTA', 'QUARENTA', 'CINQUENTA', 'SESSENTA',
19
- 'SETENTA', 'OITENTA', 'NOVENTA']
20
- }.freeze
21
- A1000 = {
22
- pt: ['', 'CEM', 'CENTO', 'DUZENTOS', 'TREZENTOS', 'QUATROCENTOS',
23
- 'QUINHENTOS', 'SEISCENTOS', 'SETECENTOS', 'OITOCENTOS', 'NOVECENTOS'],
24
- br: ['', 'CEM', 'CENTO', 'DUZENTOS', 'TREZENTOS', 'QUATROCENTOS',
25
- 'QUINHENTOS', 'SEISCENTOS', 'SETECENTOS', 'OITOCENTOS', 'NOVECENTOS']
26
- }.freeze
27
- S1E24 = { pt: ['', 'MIL', ' MILHÃO', ' MIL MILHÃO', ' BILIÃO',
28
- ' MIL BILIÃO', ' TRILIÃO', ' MIL TRILIÃO'],
29
- br: ['', 'MIL', ' MILHÃO', ' BILHÃO', ' TRILHÃO',
30
- ' QUADRILHÃO', ' QUINTILHÃO', ' SEXTILHÃO'] }.freeze
31
- P1E24 = { pt: ['', ' MIL', ' MILHÕES', ' MIL MILHÕES', ' BILIÕES',
32
- ' MIL BILIÕES', ' TRILIÕES', ' MIL TRILIÕES'],
33
- br: ['', ' MIL', ' MILHÕES', ' BILHÕES', ' TRILHÕES',
34
- ' QUADRILHÕES', ' QUINTILHÕES', ' SEXTILHÕES'] }.freeze
4
+ require 'extenso_pt/version'
5
+ require 'extenso_pt/constantes'
6
+ require 'extenso_pt/module'
35
7
 
36
8
  # @author Hernani Rodrigues Vaz
37
9
  module ExtensoPt
38
10
  class Error < StandardError; end
39
11
 
40
- # Produz o extenso das centenas em portugues de portugal ou brasil.
41
- #
42
- # @param [Integer] mil o valor dum grupo 3 digitos a converter
43
- # @return [String] o extenso das centenas
44
- def self.e900(mil)
45
- A1000[@lc][(mil > 100 ? 1 : 0) + mil / 100] +
46
- (mil > 100 && (mil % 100).positive? ? ' E ' : '') # proposicao
47
- end
48
-
49
- # Produz o extenso das dezenas em portugues de portugal ou brasil.
50
- #
51
- # @param [Integer] mil o valor dum grupo 3 digitos a converter
52
- # @return [String] o extenso das dezenas
53
- def self.e90(mil)
54
- A0100[@lc][mil % 100 / 10] +
55
- (mil > 20 && (mil % 10).positive? ? ' E ' : '') # proposicao
56
- end
57
-
58
- # Produz o extenso das unidades em portugues de portugal ou brasil.
59
- #
60
- # @param [Integer] cem o valor dum grupo 3 digitos a converter
61
- # @return [String] o extenso das unidades
62
- def self.e9(cem)
63
- A0020[@lc][(cem < 20 ? cem : cem % 10)]
64
- end
65
-
66
- # Produz extenso parte fracionaria em portugues de portugal ou brasil.
67
- #
68
- # @return [String] o extenso da parte fracionaria dum valor monetario
69
- def self.ef99
70
- if @nf.positive?
71
- e90(@nf) + e9(@nf) + (@nf > 1 ? ' ' + @cp : ' ' + @cs)
72
- else
73
- ''
74
- end
75
- end
76
-
77
- # Produz final da moeda em portugues de portugal ou brasil.
78
- #
79
- # @return [String] o final da moeda
80
- def self.efim
81
- # proposicao DE entre parte inteira e moeda
82
- emo = @de ? ' DE' : ''
83
- # moeda singular/plural
84
- emo += @tt > 1 ? ' ' + @mp : ' ' + @ms if @tt.positive?
85
- # proposicao E entre moeda e parte fracionaria
86
- # extenso da parte fracionaria
87
- emo + (@tt.positive? && @nf.positive? ? ' E ' : '') + ef99
88
- end
89
-
90
- # Produz separador entre grupos 3 digitos
91
- #
92
- # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
93
- # @return [String] separador entre grupos 3 digitos
94
- def self.esep(pos)
95
- if pos.positive? && @ai[pos - 1].positive?
96
- @ai[pos - 1] > 100 ? ' ' : ' E '
97
- else
98
- ''
99
- end
100
- end
101
-
102
- # Produz qualificador grupo de 3 digitos em portugues de portugal ou brasil.
103
- #
104
- # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
105
- # @return [String] qualificador grupo de 3 digitos
106
- def self.e1e24(pos)
107
- if @ai[pos].positive?
108
- @ai[pos] > 1 ? P1E24[@lc][pos] : S1E24[@lc][pos]
109
- else
110
- ''
111
- end
112
- end
113
-
114
- # Produz extenso grupo 3 digitos em portugues de portugal ou brasil.
115
- #
116
- # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
117
- # @return [String] extenso grupo 3 digitos
118
- def self.edg3(pos)
119
- dg3 = if pos == 1 && @ai[pos] == 1
120
- # caso especial MIL EUROS
121
- ''
122
- else
123
- e900(@ai[pos]) + e90(@ai[pos]) + e9(@ai[pos] % 100)
124
- end
125
- # qualificador grupo de 3 digitos
126
- dg3 + e1e24(pos)
127
- end
128
-
129
- # Parametrizar controle singular/plural & proposicoes
130
- #
131
- # @return [void]
132
- def self.pcontrolo
133
- # soma grupos 1,2 (primeiros 6 digitos)
134
- @s6 = @ai[0].to_i + @ai[1].to_i * 2
135
- # soma grupos 3.. (digitos acima de 6)
136
- @m6 = @ai[2..-1].to_a.inject(:+).to_i * 2
137
- @tt = @s6 + @m6 # proposicao E & singular/plural
138
- @de = @s6.zero? && @m6.positive? # proposicao DE
139
- end
140
-
141
- # Produz o extenso dum valor monetario em portugues de portugal ou brasil.
142
- #
143
- # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
144
- # @param [String] ext extenso em construcao
145
- # @return [String] o extenso dum valor monetario
146
- def self.enumerico(pos = 0, ext = '')
147
- # testa fim do valor monetario
148
- if pos >= @ai.count
149
- # parametrizar controle singular/plural & proposicoes
150
- pcontrolo
151
-
152
- # caso especial zero
153
- (@tt + @nf).zero? ? 'ZERO ' + @mp : ext + efim
154
- else
155
- # tratamento do proximo grupo 3 digitos
156
- enumerico(pos + 1, edg3(pos) + esep(pos) + ext)
157
- end
158
- end
159
-
160
- # Parametrizar parte inteira/fracionaria do valor monetario
161
- #
162
- # @param [String] dig string de digitos rdo valor monetario
163
- # @return [void]
164
- def self.pintfra(dig)
165
- # parte inteira do valor monetario => array grupos 3 digitos
166
- # ex: 123022.12 => [22, 123]
167
- @ai = dig[/^\d+/].to_s.reverse.scan(/\d{1,3}/).map { |i| i.reverse.to_i }
168
-
169
- # parte fracionaria do valor monetario
170
- # ex: 123022.12 => 12
171
- # arredondada a 2 casas decimais (centimos/centavos)
172
- @nf = (dig[/\.\d*/].to_f * 100).round
173
- end
174
-
175
- # Converte um objeto criando extenso(s) em portugues de portugal ou brasil.
176
- #
177
- # @param [Object] objeto objeto a converter
178
- # (String, Float, Integer, Array, Range, Hash)
179
- # @return [String, Array<extensos>, Hash<extensos>] string extenso
180
- # se objecto for (String, Float, Integer),
181
- # array se objecto for (Array, Range),
182
- # hash se objecto for (Hash)
183
- def self.eobjeto(obj)
184
- if obj.is_a?(Hash)
185
- # converte os valores do Hash nos seus extensos - devolve um Hash
186
- obj.map { |k, v| [k, eobjeto(v)] }.to_h
187
- elsif obj.respond_to?(:to_a)
188
- # converte o objecto num Array com os extensos dos valores
189
- obj.to_a.map { |v| eobjeto(v) }
190
- else
191
- # converte objeto numa string de digitos
192
- # usa bigdecimal/util para evitar aritmetica binaria
193
- # (tem problemas com valores >1e12)
194
- # qualquer valor nao convertivel (ex: texto) resulta em "0.0"
195
- sdigitos = obj.to_d.to_s('F')
196
-
197
- # parametrizar parte inteira/fracionaria (@ai, @nf) do valor monetario
198
- pintfra(sdigitos)
199
-
200
- # processar extenso - valores superiores a 1e24 nao sao tratados
201
- sdigitos[/^\d+/].length <= 24 ? enumerico : ''
202
- end
203
- end
204
-
205
- # Parametrizar moeda inferindo singular a partir do plural
206
- #
207
- # @param [Hash] moeda as opcoes para parametrizar a moeda/fracao
208
- # @option moeda [Symbol] :lc locale do extenso -
209
- # portugues de portugal (:pt) ou brasil (:br)
210
- # @option moeda [String] :msingular moeda no singular -
211
- # inferido do plural menos "S"
212
- # @option moeda [String] :fsingular fracao no singular -
213
- # inferido do plural menos "S"
214
- # @option moeda [String] :mplural moeda no plural
215
- # @option moeda [String] :fplural fracao no plural
216
- # @return [void]
217
- def self.psingular(moeda)
218
- @ms = moeda[:msingular] ||
219
- (moeda[:mplural].to_s[-1] == 'S' ? moeda[:mplural][0..-2] : 'EURO')
220
- @cs = moeda[:fsingular] ||
221
- (moeda[:fplural].to_s[-1] == 'S' ? moeda[:fplural][0..-2] : 'CÊNTIMO')
222
- end
223
-
224
- # Parametrizar moeda inferindo plural a partir do singular
225
- #
226
- # @param [Hash] moeda as opcoes para parametrizar a moeda/fracao
227
- # @option moeda [Symbol] :lc locale do extenso -
228
- # portugues de portugal (:pt) ou brasil (:br)
229
- # @option moeda [String] :msingular moeda no singular
230
- # @option moeda [String] :fsingular fracao no singular
231
- # @option moeda [String] :mplural moeda no plural -
232
- # inferido do singular mais "S"
233
- # @option moeda [String] :fplural fracao no plural -
234
- # inferido do singular mais "S"
235
- # @return [void]
236
- def self.pplural(moeda)
237
- # somente [:pt, :br]
238
- @lc = LC.include?(moeda[:lc]) ? moeda[:lc] : :pt
239
-
240
- @mp = moeda[:mplural] || @ms + 'S'
241
- @cp = moeda[:fplural] || @cs + 'S'
242
- end
243
-
244
- # Produz extenso(s) de objeto(s) em portugues de portugal ou brasil.
12
+ # Produz extenso(s)) em portugues de portugal ou brasil
245
13
  #
246
14
  # @param [Hash] moeda as opcoes para parametrizar a moeda/fracao
247
15
  # @option moeda [Symbol] :lc locale do extenso -
@@ -250,10 +18,10 @@ module ExtensoPt
250
18
  # @option moeda [String] :fsingular fracao no singular
251
19
  # @option moeda [String] :mplural moeda no plural
252
20
  # @option moeda [String] :fplural fracao no plural
253
- # @return [String, Array<extensos>, Hash<extensos>] string extenso
21
+ # @return [String, Array, Hash] string extenso
254
22
  # se objecto for (String, Float, Integer),
255
- # array se objecto for (Array, Range),
256
- # hash se objecto for (Hash)
23
+ # array<extensos> se objecto for (Array, Range),
24
+ # hash<extensos> se objecto for (Hash)
257
25
  def extenso(moeda = { lc: :pt, msingular: 'EURO', fsingular: 'CÊNTIMO' })
258
26
  # parametrizacao por defeito para :br
259
27
  if moeda[:lc] == :br && !moeda[:msingular] && !moeda[:mplural]
@@ -264,8 +32,8 @@ module ExtensoPt
264
32
  ExtensoPt.psingular(moeda)
265
33
  ExtensoPt.pplural(moeda)
266
34
 
267
- # extenso do objeto
268
- ExtensoPt.eobjeto(self)
35
+ # cria extenso(s) em portugues de portugal ou brasil
36
+ ExtensoPt.o2e(self)
269
37
  end
270
38
  end
271
39
 
@@ -284,17 +52,68 @@ class Range
284
52
  include ExtensoPt
285
53
  end
286
54
 
287
- # permite obter o extenso dum Float
55
+ # permite obter o extenso de Float
288
56
  class Float
289
57
  include ExtensoPt
290
58
  end
291
59
 
292
- # permite obter o extenso dum Integer
60
+ # permite obter o extenso ou numeral romano de Integer
293
61
  class Integer
294
62
  include ExtensoPt
63
+
64
+ # Produz numeracao romana a partir do inteiro
65
+ #
66
+ # @return [String] numeracao romana
67
+ def romana
68
+ return "-#{i2r(-self)}" if negative?
69
+
70
+ i2r(self)
71
+ end
72
+
73
+ # Recursivamente produz numeral romano
74
+ #
75
+ # @param [Integer] numero a converter em numeral romano
76
+ # @return [String] numeral romano
77
+ def i2r(numero)
78
+ return '' if numero.zero?
79
+
80
+ ROMAN.each { |r, v| return r.to_s + i2r(numero - v) if v <= numero }
81
+ end
295
82
  end
296
83
 
297
- # permite obter o extenso duma String de digitos
84
+ # permite obter o extenso duma string de digitos ou
85
+ # inteiro duma string numeral romano
298
86
  class String
299
87
  include ExtensoPt
88
+
89
+ # Testa se string contem numeracao romana
90
+ #
91
+ # @return [true, false] sim ou nao numeracao romana
92
+ def romana?
93
+ RO_RE.match?(upcase)
94
+ end
95
+
96
+ # Produz inteiro a partir da numeracao romana
97
+ # ou numeracao romana a partir de string digitos
98
+ #
99
+ # @return [Integer, String] inteiro ou numeracao romana
100
+ def romana
101
+ return -self[/[^-]+/].romana if /-+/.match?(self)
102
+ return self[/^\d+/].to_i.romana if /^\d+/.match?(self)
103
+ return 0 unless romana?
104
+
105
+ r2i(upcase, 0)
106
+ end
107
+
108
+ # Recursivamente produz inteiro
109
+ #
110
+ # @param [String] numeral romano em convercao
111
+ # @param [Integer] ultimo numeral convertido
112
+ # @return [Integer] inteiro do numeral romano
113
+ def r2i(numeral, ultimo)
114
+ return 0 if numeral.empty?
115
+
116
+ v = ROMAN[numeral[-1].to_sym]
117
+ v < ultimo ? (r2i(numeral.chop, v) - v) : (r2i(numeral.chop, v) + v)
118
+ end
300
119
  end
metadata CHANGED
@@ -1,76 +1,76 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: extenso_pt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.7
4
+ version: 0.5.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hernâni Rodrigues Vaz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-30 00:00:00.000000000 Z
11
+ date: 2019-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bigdecimal
14
+ name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.4.4
19
+ version: '1.17'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.4.4
26
+ version: '1.17'
27
27
  - !ruby/object:Gem::Dependency
28
- name: bundler
28
+ name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.17'
33
+ version: '5.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.17'
40
+ version: '5.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: minitest
42
+ name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '5.0'
47
+ version: '10.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '5.0'
54
+ version: '10.0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rake
56
+ name: bigdecimal
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
62
- type: :development
61
+ version: 1.4.4
62
+ type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
69
- description: Produz valores monetários por extenso em portugês de portugal ou brasil.
70
- Os valores podem ser um numerico, uma string de digitos ou um conjunto destes (array,
71
- range, hash). O extenso pode ser produzido na escala longa (utilizada em todos os
72
- países lusófonos) ou na escala curta (utilizada no Brasil). Pode ainda escolher
73
- a moeda e a fração da moeda.
68
+ version: 1.4.4
69
+ description: Converte valores monetários em extenso de portugês de portugal, brasil
70
+ ou numeracao romana. Os valores podem ser um numerico, uma string de digitos ou
71
+ um conjunto destes (array, range, hash). O extenso pode ser produzido na escala
72
+ longa (utilizada em todos os países lusófonos) ou na escala curta (utilizada no
73
+ Brasil). Pode ainda converter os valores em numeracao romana e vice versa.
74
74
  email:
75
75
  - hernanirvaz@gmail.com
76
76
  executables: []
@@ -89,6 +89,8 @@ files:
89
89
  - bin/setup
90
90
  - extenso_pt.gemspec
91
91
  - lib/extenso_pt.rb
92
+ - lib/extenso_pt/constantes.rb
93
+ - lib/extenso_pt/module.rb
92
94
  - lib/extenso_pt/version.rb
93
95
  homepage: https://github.com/hernanilr/extenso_pt
94
96
  licenses:
@@ -114,5 +116,6 @@ requirements: []
114
116
  rubygems_version: 3.0.3
115
117
  signing_key:
116
118
  specification_version: 4
117
- summary: Produz valores monetários por extenso em portugês de portugal ou brasil.
119
+ summary: Converte valores monetários em extenso de portugês de portugal, brasil ou
120
+ numeracao romana.
118
121
  test_files: []