trafficbroker-numb 0.2.0
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.
- data/LICENSE +20 -0
- data/README.rdoc +161 -0
- data/Rakefile +56 -0
- data/VERSION.yml +4 -0
- data/lib/numb.rb +424 -0
- data/test/numb_test.rb +246 -0
- data/test/test_helper.rb +6 -0
- metadata +61 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 TrafficBroker Ltd.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
= numb
|
2
|
+
|
3
|
+
Returns any numbers, currency or percentages it can find.
|
4
|
+
|
5
|
+
Currencies are returned using the standard currency codes (see wikipedia for example)
|
6
|
+
{:value => 10.00, :percent => true, :currency => 'EUR'}
|
7
|
+
Note: Currently, 'kr' will return 'DKK' even though this is the currency symbol for
|
8
|
+
Sweden, Danmark and Norway. This issue exists for other currencies as well.
|
9
|
+
New Options:
|
10
|
+
:require =>
|
11
|
+
:currency
|
12
|
+
:value
|
13
|
+
:percent
|
14
|
+
Throws an error if the required field isn't there. Can be combined:
|
15
|
+
Numb.new(:require => [:currency, :value])
|
16
|
+
|
17
|
+
:split => ['<br/>', '//']
|
18
|
+
Splits the fields based on the passed variables in the order they are passed
|
19
|
+
|
20
|
+
:debug => true
|
21
|
+
Prints out debugging info.
|
22
|
+
|
23
|
+
== Examples
|
24
|
+
|
25
|
+
Numb.new.parse("US$1.00 ") # => {:currency => 'USD', :value => 1.00}
|
26
|
+
|
27
|
+
Numb.new.parse('12.34%') # => {:percent => true, :value => 12.34}
|
28
|
+
|
29
|
+
== Supported Currencies
|
30
|
+
|
31
|
+
ALL
|
32
|
+
AFN
|
33
|
+
ARS
|
34
|
+
AWG
|
35
|
+
AUD
|
36
|
+
AZN
|
37
|
+
BSD
|
38
|
+
BBD
|
39
|
+
BYR
|
40
|
+
BZD
|
41
|
+
BMD
|
42
|
+
BOB
|
43
|
+
BAM
|
44
|
+
BWP
|
45
|
+
BGN
|
46
|
+
BRL
|
47
|
+
BND
|
48
|
+
KHR
|
49
|
+
CAD
|
50
|
+
KYD
|
51
|
+
CLP
|
52
|
+
CNY
|
53
|
+
COP
|
54
|
+
CRC
|
55
|
+
HRK
|
56
|
+
CUP
|
57
|
+
CZK
|
58
|
+
DOP
|
59
|
+
XCD
|
60
|
+
EGP
|
61
|
+
SVC
|
62
|
+
EEK
|
63
|
+
FKP
|
64
|
+
FJD
|
65
|
+
GHC
|
66
|
+
GIP
|
67
|
+
GTQ
|
68
|
+
GGP
|
69
|
+
GYD
|
70
|
+
HNL
|
71
|
+
HKD
|
72
|
+
HUF
|
73
|
+
ISK
|
74
|
+
IDR
|
75
|
+
IRR
|
76
|
+
IMP
|
77
|
+
ILS
|
78
|
+
JMD
|
79
|
+
JPY
|
80
|
+
JEP
|
81
|
+
KZT
|
82
|
+
KPW
|
83
|
+
KRW
|
84
|
+
KGS
|
85
|
+
LAK
|
86
|
+
LVL
|
87
|
+
LBP
|
88
|
+
LRD
|
89
|
+
CHF
|
90
|
+
LTL
|
91
|
+
MKD
|
92
|
+
MYR
|
93
|
+
MUR
|
94
|
+
MXN
|
95
|
+
MNT
|
96
|
+
MZN
|
97
|
+
NAD
|
98
|
+
NPR
|
99
|
+
ANG
|
100
|
+
NZD
|
101
|
+
NIO
|
102
|
+
NGN
|
103
|
+
KPW
|
104
|
+
NOK
|
105
|
+
OMR
|
106
|
+
PKR
|
107
|
+
PAB
|
108
|
+
PYG
|
109
|
+
PEN
|
110
|
+
PHP
|
111
|
+
PLN
|
112
|
+
QAR
|
113
|
+
RON
|
114
|
+
RUB
|
115
|
+
SHP
|
116
|
+
SAR
|
117
|
+
RSD
|
118
|
+
SCR
|
119
|
+
SBD
|
120
|
+
SOS
|
121
|
+
ZAR
|
122
|
+
KRW
|
123
|
+
LKR
|
124
|
+
CHF
|
125
|
+
SRD
|
126
|
+
SYP
|
127
|
+
TWD
|
128
|
+
THB
|
129
|
+
TTD
|
130
|
+
TRY
|
131
|
+
TRL
|
132
|
+
TVD
|
133
|
+
UAH
|
134
|
+
UYU
|
135
|
+
UZS
|
136
|
+
VEF
|
137
|
+
VND
|
138
|
+
YER
|
139
|
+
ZWD
|
140
|
+
|
141
|
+
== Duplicate currencies which will not correctly identify
|
142
|
+
PRIMARY = {
|
143
|
+
'£' => 'GBP',
|
144
|
+
'kr' => 'DKK',
|
145
|
+
'$' => 'USD',
|
146
|
+
'¥' => 'JPY',
|
147
|
+
'ƒ' => 'AWG',
|
148
|
+
}
|
149
|
+
|
150
|
+
DUPLICATES = {
|
151
|
+
'£' => ['EGP', 'FKP', 'GIP', 'GGP', 'IMP', 'JEP', 'LBP', 'SHP', 'SYP', 'EEK'],
|
152
|
+
'kr' => ['ISK', 'NOK', 'SEK'],
|
153
|
+
'$' => ['ARS', 'AUD', 'BSD', 'BBD', 'BMD', 'BND', 'CAD', 'KYD', 'CLP', 'COP',
|
154
|
+
'FJD', 'GYD', 'HKD', 'LRD', 'MXN', 'NAD', 'NZD', 'SGD', 'SBD', 'SVC', 'TVD', 'SRD', 'XCD'],
|
155
|
+
'¥' => 'CNY',
|
156
|
+
'ƒ' => 'ANG',
|
157
|
+
}
|
158
|
+
|
159
|
+
== Copyright
|
160
|
+
|
161
|
+
Copyright (c) 2009 TrafficBroker Ltd. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "numb"
|
8
|
+
gem.summary = %Q{TODO}
|
9
|
+
gem.email = "technology@trafficbroker.co.uk"
|
10
|
+
gem.homepage = "http://github.com/trafficbroker/numb"
|
11
|
+
gem.authors = ["trafficbroker"]
|
12
|
+
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'rake/testtask'
|
20
|
+
Rake::TestTask.new(:test) do |test|
|
21
|
+
test.libs << 'lib' << 'test'
|
22
|
+
test.pattern = 'test/**/*_test.rb'
|
23
|
+
test.verbose = true
|
24
|
+
end
|
25
|
+
|
26
|
+
begin
|
27
|
+
require 'rcov/rcovtask'
|
28
|
+
Rcov::RcovTask.new do |test|
|
29
|
+
test.libs << 'test'
|
30
|
+
test.pattern = 'test/**/*_test.rb'
|
31
|
+
test.verbose = true
|
32
|
+
end
|
33
|
+
rescue LoadError
|
34
|
+
task :rcov do
|
35
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
task :default => :test
|
41
|
+
|
42
|
+
require 'rake/rdoctask'
|
43
|
+
Rake::RDocTask.new do |rdoc|
|
44
|
+
if File.exist?('VERSION.yml')
|
45
|
+
config = YAML.load(File.read('VERSION.yml'))
|
46
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
47
|
+
else
|
48
|
+
version = ""
|
49
|
+
end
|
50
|
+
|
51
|
+
rdoc.rdoc_dir = 'rdoc'
|
52
|
+
rdoc.title = "numb #{version}"
|
53
|
+
rdoc.rdoc_files.include('README*')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
end
|
56
|
+
|
data/VERSION.yml
ADDED
data/lib/numb.rb
ADDED
@@ -0,0 +1,424 @@
|
|
1
|
+
# Returns any numbers, currency or percentages it can find
|
2
|
+
# Currencies are returned using the standard currency codes (see wikipedia for example)
|
3
|
+
# {:value => 10.00, :percent => true, :currency => 'EUR'}
|
4
|
+
# Note: Currently, 'kr' will return 'DKK' even though this is the currency symbol for
|
5
|
+
# Sweden, Danmark and Norway
|
6
|
+
# New Options:
|
7
|
+
# :require =>
|
8
|
+
# :currency
|
9
|
+
# :value
|
10
|
+
# :percent
|
11
|
+
# Throws an error if the required field isn't there. Can be combined:
|
12
|
+
# Numb.new(:require => [:currency, :value])
|
13
|
+
#
|
14
|
+
# :split => ['<br/>', '//']
|
15
|
+
# Splits the fields based on the passed variables in the order they are passed
|
16
|
+
#
|
17
|
+
# :debug => true
|
18
|
+
# Prints out debugging info.
|
19
|
+
|
20
|
+
class Numb
|
21
|
+
def initialize(opts = {})
|
22
|
+
@opts = opts
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse(text)
|
26
|
+
return do_parse(text) unless @opts.has_key?(:split)
|
27
|
+
text_arr = get_split(text)
|
28
|
+
res = []
|
29
|
+
text_arr.each do |text|
|
30
|
+
res << do_parse(text)
|
31
|
+
end
|
32
|
+
res
|
33
|
+
end
|
34
|
+
|
35
|
+
def currency_find(sym)
|
36
|
+
match = CURRENCIES.find{|k,v| m = sym.match('^'+k+'$')}
|
37
|
+
return nil unless match
|
38
|
+
match[1]
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def do_parse(text)
|
44
|
+
res = {}
|
45
|
+
text.gsub!(NBSP, ' ')
|
46
|
+
new_res, text = currency(text)
|
47
|
+
res.merge!(new_res)
|
48
|
+
new_res, text = percent(text)
|
49
|
+
res.merge!(new_res)
|
50
|
+
new_res, text = number(text)
|
51
|
+
res.merge!(new_res)
|
52
|
+
return nil if res == {}
|
53
|
+
res
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_split(text)
|
57
|
+
arr = [text]
|
58
|
+
split = @opts[:split]
|
59
|
+
split = [split] unless split.respond_to? :each
|
60
|
+
split.each do |sp|
|
61
|
+
temp = []
|
62
|
+
arr.each do |t|
|
63
|
+
temp = temp + t.split(sp)
|
64
|
+
end
|
65
|
+
arr = temp.flatten
|
66
|
+
end
|
67
|
+
arr
|
68
|
+
end
|
69
|
+
|
70
|
+
def money_regexp
|
71
|
+
return @money_regexp if @money_regexp
|
72
|
+
currencies = CURRENCIES.keys
|
73
|
+
@money_regexp = Regexp.new('(?:[^A-Z]|^)(' + currencies.join("|") + ')(?:[^A-Z\$]|$)', Regexp::IGNORECASE)
|
74
|
+
debug 'currency regexp: '+@money_regexp.inspect
|
75
|
+
@money_regexp
|
76
|
+
end
|
77
|
+
|
78
|
+
def currency(string)
|
79
|
+
match = string.match(money_regexp)
|
80
|
+
debug "currency match: #{match.inspect}"
|
81
|
+
return failed(string, :currency) unless match
|
82
|
+
currency_symbol = match[1]
|
83
|
+
currency = CURRENCIES[currency_symbol]
|
84
|
+
debug "currency currency: #{currency}, currency_symbol: #{currency_symbol}"
|
85
|
+
currency = currency_find(currency_symbol) unless currency
|
86
|
+
debug "currency currency2: #{currency}"
|
87
|
+
return failed(string, :currency) unless currency
|
88
|
+
[{:currency => currency}, string.gsub(currency_symbol, '')]
|
89
|
+
end
|
90
|
+
|
91
|
+
def percent(string)
|
92
|
+
return failed(string, :percent) unless string.match(/%/)
|
93
|
+
[{:percent => true}, string.gsub('%', '')]
|
94
|
+
end
|
95
|
+
|
96
|
+
def number(string)
|
97
|
+
stripped = string.match(/((?:\d|-)?(?:\d|\d,)*\.?\d+)/)
|
98
|
+
stripped ? [{:value => stripped[0].gsub(',','').to_f}, string.gsub(stripped[0], '')] : failed(string, :value)
|
99
|
+
end
|
100
|
+
|
101
|
+
def failed(string, type)
|
102
|
+
if check_require(type)
|
103
|
+
chars = (0..(string.size-1)).map {|i| "#{string[i]}.chr"}.join('+')
|
104
|
+
raise "ERROR: #{type.to_s.capitalize} not found and was required.\nText:\n#{string}\nCharacter Codes:[#{chars}]"
|
105
|
+
end
|
106
|
+
[{}, string]
|
107
|
+
end
|
108
|
+
|
109
|
+
def check_require(type)
|
110
|
+
return false unless @opts.has_key?(:require)
|
111
|
+
keys = []
|
112
|
+
keys << @opts[:require]
|
113
|
+
keys.flatten.each do |k|
|
114
|
+
return true if k == type
|
115
|
+
end
|
116
|
+
false
|
117
|
+
end
|
118
|
+
|
119
|
+
def debug(message)
|
120
|
+
puts message if @opts[:debug]
|
121
|
+
end
|
122
|
+
|
123
|
+
NBSP = 194.chr+160.chr
|
124
|
+
|
125
|
+
CURRENCIES =
|
126
|
+
{
|
127
|
+
'AU\$' => 'AUD',
|
128
|
+
|
129
|
+
'CA\$' => 'CAD',
|
130
|
+
|
131
|
+
'DKK' => 'DKK',
|
132
|
+
'kr' => 'DKK',
|
133
|
+
'kr'+NBSP => 'DKK',
|
134
|
+
'kr ' => 'DKK',
|
135
|
+
|
136
|
+
'EUR' => 'EUR',
|
137
|
+
'€' => 'EUR',
|
138
|
+
194.chr+128.chr => "EUR",
|
139
|
+
'€' => 'EUR',
|
140
|
+
'€' => 'EUR',
|
141
|
+
|
142
|
+
'GBP' => 'GBP',
|
143
|
+
'\243' => 'GBP',
|
144
|
+
'£' => 'GBP',
|
145
|
+
'£' => 'GBP',
|
146
|
+
'UK' => "GBP",
|
147
|
+
'UK\243' => "GBP",
|
148
|
+
'UK£' => "GBP",
|
149
|
+
'UK'+239.chr+189.chr+163.chr => "GBP",
|
150
|
+
'£' => 'GBP',
|
151
|
+
'£' => 'GBP',
|
152
|
+
|
153
|
+
'Rs' => 'INR',
|
154
|
+
'INR' => 'INR',
|
155
|
+
|
156
|
+
239.chr+189.chr+165.chr => 'JPY',
|
157
|
+
'¥' => 'JPY',
|
158
|
+
'¥' => 'JPY',
|
159
|
+
'¥' => 'JPY',
|
160
|
+
165.chr => 'JPY',
|
161
|
+
|
162
|
+
'NZ\$' => 'NZD',
|
163
|
+
|
164
|
+
'SEK' => 'SEK',
|
165
|
+
|
166
|
+
'S\$' => 'SGD',
|
167
|
+
'SGD' => 'SGD',
|
168
|
+
|
169
|
+
'USD' => 'USD',
|
170
|
+
'US\$' => 'USD',
|
171
|
+
'\$' => 'USD',
|
172
|
+
|
173
|
+
# generated codes
|
174
|
+
'ALL' => 'ALL',
|
175
|
+
'AFN' => 'AFN',
|
176
|
+
'ARS' => 'ARS',
|
177
|
+
'AWG' => 'AWG',
|
178
|
+
'AUD' => 'AUD',
|
179
|
+
'AZN' => 'AZN',
|
180
|
+
'BSD' => 'BSD',
|
181
|
+
'BBD' => 'BBD',
|
182
|
+
'BYR' => 'BYR',
|
183
|
+
'BZD' => 'BZD',
|
184
|
+
'BMD' => 'BMD',
|
185
|
+
'BOB' => 'BOB',
|
186
|
+
'BAM' => 'BAM',
|
187
|
+
'BWP' => 'BWP',
|
188
|
+
'BGN' => 'BGN',
|
189
|
+
'BRL' => 'BRL',
|
190
|
+
'BND' => 'BND',
|
191
|
+
'KHR' => 'KHR',
|
192
|
+
'CAD' => 'CAD',
|
193
|
+
'KYD' => 'KYD',
|
194
|
+
'CLP' => 'CLP',
|
195
|
+
'CNY' => 'CNY',
|
196
|
+
'COP' => 'COP',
|
197
|
+
'CRC' => 'CRC',
|
198
|
+
'HRK' => 'HRK',
|
199
|
+
'CUP' => 'CUP',
|
200
|
+
'CZK' => 'CZK',
|
201
|
+
'DOP' => 'DOP',
|
202
|
+
'XCD' => 'XCD',
|
203
|
+
'EGP' => 'EGP',
|
204
|
+
'SVC' => 'SVC',
|
205
|
+
'EEK' => 'EEK',
|
206
|
+
'FKP' => 'FKP',
|
207
|
+
'FJD' => 'FJD',
|
208
|
+
'GHC' => 'GHC',
|
209
|
+
'GIP' => 'GIP',
|
210
|
+
'GTQ' => 'GTQ',
|
211
|
+
'GGP' => 'GGP',
|
212
|
+
'GYD' => 'GYD',
|
213
|
+
'HNL' => 'HNL',
|
214
|
+
'HKD' => 'HKD',
|
215
|
+
'HUF' => 'HUF',
|
216
|
+
'ISK' => 'ISK',
|
217
|
+
'IDR' => 'IDR',
|
218
|
+
'IRR' => 'IRR',
|
219
|
+
'IMP' => 'IMP',
|
220
|
+
'ILS' => 'ILS',
|
221
|
+
'JMD' => 'JMD',
|
222
|
+
'JPY' => 'JPY',
|
223
|
+
'JEP' => 'JEP',
|
224
|
+
'KZT' => 'KZT',
|
225
|
+
'KPW' => 'KPW',
|
226
|
+
'KRW' => 'KRW',
|
227
|
+
'KGS' => 'KGS',
|
228
|
+
'LAK' => 'LAK',
|
229
|
+
'LVL' => 'LVL',
|
230
|
+
'LBP' => 'LBP',
|
231
|
+
'LRD' => 'LRD',
|
232
|
+
'CHF' => 'CHF',
|
233
|
+
'LTL' => 'LTL',
|
234
|
+
'MKD' => 'MKD',
|
235
|
+
'MYR' => 'MYR',
|
236
|
+
'MUR' => 'MUR',
|
237
|
+
'MXN' => 'MXN',
|
238
|
+
'MNT' => 'MNT',
|
239
|
+
'MZN' => 'MZN',
|
240
|
+
'NAD' => 'NAD',
|
241
|
+
'NPR' => 'NPR',
|
242
|
+
'ANG' => 'ANG',
|
243
|
+
'NZD' => 'NZD',
|
244
|
+
'NIO' => 'NIO',
|
245
|
+
'NGN' => 'NGN',
|
246
|
+
'KPW' => 'KPW',
|
247
|
+
'NOK' => 'NOK',
|
248
|
+
'OMR' => 'OMR',
|
249
|
+
'PKR' => 'PKR',
|
250
|
+
'PAB' => 'PAB',
|
251
|
+
'PYG' => 'PYG',
|
252
|
+
'PEN' => 'PEN',
|
253
|
+
'PHP' => 'PHP',
|
254
|
+
'PLN' => 'PLN',
|
255
|
+
'QAR' => 'QAR',
|
256
|
+
'RON' => 'RON',
|
257
|
+
'RUB' => 'RUB',
|
258
|
+
'SHP' => 'SHP',
|
259
|
+
'SAR' => 'SAR',
|
260
|
+
'RSD' => 'RSD',
|
261
|
+
'SCR' => 'SCR',
|
262
|
+
'SBD' => 'SBD',
|
263
|
+
'SOS' => 'SOS',
|
264
|
+
'ZAR' => 'ZAR',
|
265
|
+
'KRW' => 'KRW',
|
266
|
+
'LKR' => 'LKR',
|
267
|
+
'CHF' => 'CHF',
|
268
|
+
'SRD' => 'SRD',
|
269
|
+
'SYP' => 'SYP',
|
270
|
+
'TWD' => 'TWD',
|
271
|
+
'THB' => 'THB',
|
272
|
+
'TTD' => 'TTD',
|
273
|
+
'TRY' => 'TRY',
|
274
|
+
'TRL' => 'TRL',
|
275
|
+
'TVD' => 'TVD',
|
276
|
+
'UAH' => 'UAH',
|
277
|
+
'UYU' => 'UYU',
|
278
|
+
'UZS' => 'UZS',
|
279
|
+
'VEF' => 'VEF',
|
280
|
+
'VND' => 'VND',
|
281
|
+
'YER' => 'YER',
|
282
|
+
'ZWD' => 'ZWD',
|
283
|
+
|
284
|
+
# Semi generated
|
285
|
+
'Lek' => 'ALL',
|
286
|
+
'ƒ' => 'AWG',
|
287
|
+
'p.' => 'BYR',
|
288
|
+
'BZ$' => 'BZD',
|
289
|
+
'$b' => 'BOB',
|
290
|
+
'KM' => 'BAM',
|
291
|
+
'P' => 'BWP',
|
292
|
+
'R$' => 'BRL',
|
293
|
+
'kn' => 'HRK',
|
294
|
+
'Kč' => 'CZK',
|
295
|
+
'RD$' => 'DOP',
|
296
|
+
162.chr => 'GHC',
|
297
|
+
'Q' => 'GTQ',
|
298
|
+
'L' => 'HNL',
|
299
|
+
'Ft' => 'HUF',
|
300
|
+
'Rp' => 'IDR',
|
301
|
+
'J$' => 'JMD',
|
302
|
+
'Ls' => 'LVL',
|
303
|
+
'CHF' => 'CHF',
|
304
|
+
'Lt' => 'LTL',
|
305
|
+
'RM' => 'MYR',
|
306
|
+
'MT' => 'MZN',
|
307
|
+
'C$' => 'NIO',
|
308
|
+
'B/.' => 'PAB',
|
309
|
+
'Gs' => 'PYG',
|
310
|
+
'S/.' => 'PEN',
|
311
|
+
'Php' => 'PHP',
|
312
|
+
'zł' => 'PLN',
|
313
|
+
'lei' => 'RON',
|
314
|
+
'S' => 'SOS',
|
315
|
+
'R' => 'ZAR',
|
316
|
+
'CHF' => 'CHF',
|
317
|
+
'NT$' => 'TWD',
|
318
|
+
'TT$' => 'TTD',
|
319
|
+
'YTL' => 'TRY',
|
320
|
+
'$U' => 'UYU',
|
321
|
+
'Bs' => 'VEF',
|
322
|
+
'Z$' => 'ZWD',
|
323
|
+
|
324
|
+
# HTML unicode
|
325
|
+
'؋' => 'AFN',
|
326
|
+
'ƒ' => 'AWG',
|
327
|
+
'ман' => 'AZN',
|
328
|
+
'лв' => 'BGN',
|
329
|
+
'៛' => 'KHR',
|
330
|
+
'₡' => 'CRC',
|
331
|
+
'₱' => 'CUP',
|
332
|
+
'Kč' => 'CZK',
|
333
|
+
'₨' => 'INR',
|
334
|
+
'﷼' => 'IRR',
|
335
|
+
'₪' => 'ILS',
|
336
|
+
'лв' => 'KZT',
|
337
|
+
'₩' => 'KPW',
|
338
|
+
'₩' => 'KRW',
|
339
|
+
'лв' => 'KGS',
|
340
|
+
'₭' => 'LAK',
|
341
|
+
'ден' => 'MKD',
|
342
|
+
'₨' => 'MUR',
|
343
|
+
'₮' => 'MNT',
|
344
|
+
'₨' => 'NPR',
|
345
|
+
'₦' => 'NGN',
|
346
|
+
'₩' => 'KPW',
|
347
|
+
'﷼' => 'OMR',
|
348
|
+
'₨' => 'PKR',
|
349
|
+
'zł' => 'PLN',
|
350
|
+
'﷼' => 'QAR',
|
351
|
+
'руб' => 'RUB',
|
352
|
+
'﷼' => 'SAR',
|
353
|
+
'Дин.' => 'RSD',
|
354
|
+
'₨' => 'SCR',
|
355
|
+
'₩' => 'KRW',
|
356
|
+
'₨' => 'LKR',
|
357
|
+
'฿' => 'THB',
|
358
|
+
'₤' => 'TRL',
|
359
|
+
'₴' => 'UAH',
|
360
|
+
'лв' => 'UZS',
|
361
|
+
'₫' => 'VND',
|
362
|
+
'﷼' => 'YER',
|
363
|
+
}
|
364
|
+
|
365
|
+
DUPLICATES = {
|
366
|
+
'£' => ['EGP', 'FKP', 'GIP', 'GGP', 'IMP', 'JEP', 'LBP', 'SHP', 'SYP', 'EEK'],
|
367
|
+
'kr' => ['ISK', 'NOK', 'SEK'],
|
368
|
+
'$' => ['ARS', 'AUD', 'BSD', 'BBD', 'BMD', 'BND', 'CAD', 'KYD', 'CLP', 'COP',
|
369
|
+
'FJD', 'GYD', 'HKD', 'LRD', 'MXN', 'NAD', 'NZD', 'SGD', 'SBD', 'SVC', 'TVD', 'SRD', 'XCD'],
|
370
|
+
'¥' => 'CNY',
|
371
|
+
'ƒ' => 'ANG',
|
372
|
+
'ƒ' => 'ANG',
|
373
|
+
}
|
374
|
+
|
375
|
+
PROBLEMS = {
|
376
|
+
# 8364.chr => 'EUR',
|
377
|
+
# 1547.chr => 'AFN',
|
378
|
+
# 1084.chr+1072.chr+1085.chr => 'AZN',
|
379
|
+
# 1083.chr+1074.chr => 'BGN',
|
380
|
+
# 6107.chr => 'KHR',
|
381
|
+
# 8353.chr => 'CRC',
|
382
|
+
# 8369.chr => 'CUP',
|
383
|
+
# 8360.chr => 'INR',
|
384
|
+
# 65020.chr => 'IRR',
|
385
|
+
# 8362.chr => 'ILS',
|
386
|
+
# 1083.chr+1074.chr => 'KZT',
|
387
|
+
# 8361.chr => 'KPW',
|
388
|
+
# 8361.chr => 'KRW',
|
389
|
+
# 1083.chr+1074.chr => 'KGS',
|
390
|
+
# 8365.chr => 'LAK',
|
391
|
+
# 1076.chr+1077.chr+1085.chr => 'MKD',
|
392
|
+
# 8360.chr => 'MUR',
|
393
|
+
# 8366.chr => 'MNT',
|
394
|
+
# 8360.chr => 'NPR',
|
395
|
+
# 8358.chr => 'NGN',
|
396
|
+
# 8361.chr => 'KPW',
|
397
|
+
# 65020.chr => 'OMR',
|
398
|
+
# 8360.chr => 'PKR',
|
399
|
+
# 65020.chr => 'QAR',
|
400
|
+
# 1088.chr+1091.chr+1073.chr => 'RUB',
|
401
|
+
# 65020.chr => 'SAR',
|
402
|
+
# 1044.chr+1080.chr+1085.chr+46.chr => 'RSD',
|
403
|
+
# 8360.chr => 'SCR',
|
404
|
+
# 8361.chr => 'KRW',
|
405
|
+
# 8360.chr => 'LKR',
|
406
|
+
# 3647.chr => 'THB',
|
407
|
+
# 8356.chr => 'TRL',
|
408
|
+
# 8372.chr => 'UAH',
|
409
|
+
# 1083.chr+1074.chr => 'UZS',
|
410
|
+
# 8363.chr => 'VND',
|
411
|
+
# 65020.chr => 'YER',
|
412
|
+
# 8363.chr => 'VND',
|
413
|
+
# 65020.chr => 'YER',
|
414
|
+
}
|
415
|
+
|
416
|
+
|
417
|
+
end
|
418
|
+
|
419
|
+
|
420
|
+
class String
|
421
|
+
def escape
|
422
|
+
return self.dump[1..-2]
|
423
|
+
end
|
424
|
+
end
|
data/test/numb_test.rb
ADDED
@@ -0,0 +1,246 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require File.join(File.dirname(__FILE__), "test_helper")
|
3
|
+
|
4
|
+
class NumbTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
# Percentages
|
7
|
+
def test_percentage
|
8
|
+
expected = {:percent => true, :value => 12.34}
|
9
|
+
assert_equal expected, Numb.new.parse('12.34%')
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_percentage_100
|
13
|
+
expected = {:percent => true, :value => 100.0}
|
14
|
+
assert_equal expected, Numb.new.parse('100.00%')
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_percentage_fail_without_figure
|
18
|
+
expected = nil
|
19
|
+
assert_equal expected, Numb.new.parse('n/a')
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_percentage_find_percent_only
|
23
|
+
expected = {:percent => true}
|
24
|
+
assert_equal expected, Numb.new.parse('blah%')
|
25
|
+
end
|
26
|
+
|
27
|
+
# Numbers
|
28
|
+
def test_number_without_percent_sign
|
29
|
+
expected = {:value => 12.34}
|
30
|
+
assert_equal expected, Numb.new.parse('12.34')
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_number_with_comma
|
34
|
+
expected = {:value => 4012.34}
|
35
|
+
assert_equal expected, Numb.new.parse('4,012.34')
|
36
|
+
expected = {:value => 4000012.34}
|
37
|
+
assert_equal expected, Numb.new.parse('4,000,012.34')
|
38
|
+
end
|
39
|
+
|
40
|
+
# Money
|
41
|
+
def test_gbp
|
42
|
+
expected = {:currency => 'GBP', :value => 12.34}
|
43
|
+
assert_equal expected, Numb.new.parse("£12.34")
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_gbp_with_chrs
|
47
|
+
expected = {:currency => 'GBP', :value => 12.34}
|
48
|
+
assert_equal expected, Numb.new.parse(194.chr+163.chr+'12.34')
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_currencies_with_extra
|
52
|
+
expected = {:currency => 'AUD'}
|
53
|
+
assert_equal expected, Numb.new.parse('AU$')
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_various_currencies
|
57
|
+
expected = {:currency => 'GBP'}
|
58
|
+
assert_equal expected, Numb.new.parse("UK£")
|
59
|
+
assert_equal expected, Numb.new.parse(85.chr+75.chr+239.chr+191.chr+189.chr+239.chr)
|
60
|
+
expected = {:currency => 'AUD', :percent => true}
|
61
|
+
assert_equal expected, Numb.new.parse('AU$)%')
|
62
|
+
expected = {:currency => 'CAD'}
|
63
|
+
assert_equal expected, Numb.new.parse("(CA$)")
|
64
|
+
expected = {:currency => 'USD', :value => 1.00}
|
65
|
+
assert_equal expected, Numb.new.parse("US$1.00 ")
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_extra_characters
|
69
|
+
expected = {:currency => 'USD'}
|
70
|
+
assert_equal expected, Numb.new.parse("US$")
|
71
|
+
expected = nil
|
72
|
+
assert_equal expected, Numb.new.parse("DS$")
|
73
|
+
expected = {:currency => 'SGD', :value => 2.0}
|
74
|
+
assert_equal expected, Numb.new.parse("2S$")
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_require
|
78
|
+
assert_raise RuntimeError do
|
79
|
+
Numb.new(:require => :currency).parse("0.00")
|
80
|
+
end
|
81
|
+
assert_raise RuntimeError do
|
82
|
+
Numb.new(:require => :value).parse("£")
|
83
|
+
end
|
84
|
+
assert_raise RuntimeError do
|
85
|
+
Numb.new(:require => :percent).parse("0.00")
|
86
|
+
end
|
87
|
+
assert_raise RuntimeError do
|
88
|
+
Numb.new(:require => [:currency, :value]).parse("0.00")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_split
|
93
|
+
expected = [{:currency => 'USD', :value => 1.00}]
|
94
|
+
assert_equal expected, Numb.new(:split => ' ').parse("US$1.00")
|
95
|
+
expected = [{:currency => 'USD', :value => 1.00}]
|
96
|
+
assert_equal expected, Numb.new(:split => /[&@]/).parse("US$1.00")
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_parse_percentage
|
100
|
+
commission = Numb.new.parse('2.5%')
|
101
|
+
expected = {:percent => true, :value => 2.5}
|
102
|
+
assert_equal expected, commission
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_parse_money
|
106
|
+
commission = Numb.new.parse("\2432.50")
|
107
|
+
expected = {:value => 2.50, :currency => "GBP"}
|
108
|
+
assert_equal expected, commission
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_parse_money_and_percent
|
112
|
+
commission = Numb.new(:split => '-').parse("10.00% - \2430.25")
|
113
|
+
expected = [{:value => 10.0, :percent => true}, {:value => 0.25, :currency => "GBP"}]
|
114
|
+
assert_equal expected, commission
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_parse_percent_and_no_money
|
118
|
+
commission = Numb.new.parse('6.00%n/a')
|
119
|
+
expected = {:value => 6.0, :percent => true}
|
120
|
+
assert_equal expected, commission
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_currency_pound
|
124
|
+
expected = {:currency => 'GBP', :value=>2.5}
|
125
|
+
assert_equal expected, Numb.new.parse("\2432.50")
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_currency_dollar
|
129
|
+
expected = {:currency => 'USD', :value => 2.50}
|
130
|
+
assert_equal expected, Numb.new.parse('$2.50')
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_currency_euro
|
134
|
+
expected = {:currency => 'EUR', :value => 2.50}
|
135
|
+
assert_equal expected, Numb.new.parse('€2.50')
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_money_happy_path
|
139
|
+
expected = {:currency => 'GBP', :value => 2.50}
|
140
|
+
assert_equal expected, Numb.new.parse("\2432.50")
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_money_with_leading_characters
|
144
|
+
expected = {:currency => 'GBP', :value => 3.00}
|
145
|
+
assert_equal expected, Numb.new.parse("3.00 \2432.50")
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_money_with_trailing_characters
|
149
|
+
expected = {:currency => 'GBP', :value => 2.5}
|
150
|
+
assert_equal expected, Numb.new.parse("\2432.50 3.00")
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_money_with_double_currency_sign
|
154
|
+
expected = {:currency => 'GBP', :value => 2.5}
|
155
|
+
assert_equal expected, Numb.new.parse("commission amount \243\2432.50")
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_money_with_comma
|
159
|
+
expected = {:currency => 'GBP', :value => 2002.5}
|
160
|
+
assert_equal expected, Numb.new.parse("\2432,002.50 3.00")
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_money_failure
|
164
|
+
expected = {:value => 2.50}
|
165
|
+
assert_equal expected, Numb.new.parse('2.50')
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_currency_unicode_hash_codes
|
169
|
+
expected = {:currency => 'RUB', :value => 2.50}
|
170
|
+
assert_equal expected, Numb.new.parse('руб2.50')
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_currency
|
174
|
+
expected = {:value => 0.0}
|
175
|
+
assert_equal expected, Numb.new.parse("0.00")
|
176
|
+
expected = {:currency => 'DKK', :value => 0.00}
|
177
|
+
assert_equal expected, Numb.new.parse("kr"+Numb::NBSP+"0.00")
|
178
|
+
expected = {:currency => 'DKK', :value => 0.00}
|
179
|
+
assert_equal expected, Numb.new.parse("kr 0.00")
|
180
|
+
expected = {:currency => 'USD', :value => 0.00}
|
181
|
+
assert_equal expected, Numb.new.parse("$0.00")
|
182
|
+
expected = {:currency => 'GBP', :value => 0.00}
|
183
|
+
assert_equal expected, Numb.new.parse("£0.00")
|
184
|
+
expected = {:currency => 'GBP', :value => 0.00}
|
185
|
+
assert_equal expected, Numb.new.parse("£0.00")
|
186
|
+
expected = {:currency => 'EUR', :value => 0.00}
|
187
|
+
assert_equal expected, Numb.new.parse("€0.00")
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_get_monies
|
191
|
+
expected = [{:currency => 'GBP', :value => 0.00}, {:currency => 'GBP', :value => 2.00}, {:currency => 'GBP', :value => 3.50}]
|
192
|
+
assert_equal expected, Numb.new(:split => ['<br/>', '//']).parse("£0.00<br/>£2.00//£3.50")
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_get_percents
|
196
|
+
expected = {:percent => true, :value => 0.00}
|
197
|
+
assert_equal expected, Numb.new.parse("0.00%")
|
198
|
+
expected = [{:percent => true, :value => 0.00}, {:percent => true, :value => 2.00}, {:percent => true, :value => 3.50}]
|
199
|
+
assert_equal expected, Numb.new(:split => ['<br/>', '//']).parse("%0.00<br/>%2.00//%3.50")
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_get_commission
|
203
|
+
expected = [
|
204
|
+
{:currency => 'GBP', :value => 45.00},
|
205
|
+
{:currency => 'GBP', :value => 45.00},
|
206
|
+
{:currency => 'GBP', :value => 45.00},
|
207
|
+
{:currency => 'GBP', :value => 1.00},
|
208
|
+
{:currency => 'GBP', :value => 6.00},
|
209
|
+
{:currency => 'GBP', :value => 1.00},
|
210
|
+
]
|
211
|
+
assert_equal expected, Numb.new(:split => ['<br/>', 'v']).parse(" £45.00<br/>\n£45.00<br/>\n£45.00<br/>£1.00<br/>£6.00v£1.00")
|
212
|
+
expected = [
|
213
|
+
{:percent => true, :value => 45.00},
|
214
|
+
{:percent => true, :value => 45.00},
|
215
|
+
{:percent => true, :value => 45.00},
|
216
|
+
{:percent => true, :value => 1.00},
|
217
|
+
{:percent => true, :value => 6.00},
|
218
|
+
{:percent => true, :value => 1.00},
|
219
|
+
]
|
220
|
+
assert_equal expected, Numb.new(:split => ['<br/>', 'v']).parse(" 45.00%<br/>\n45.00%<br/>\n45.00%<br/>1.00%<br/>6.00%v1.00%")
|
221
|
+
end
|
222
|
+
|
223
|
+
# Supported currencies
|
224
|
+
def test_japan
|
225
|
+
expected = {:currency => 'JPY', :value => 600.00}
|
226
|
+
assert_equal expected, Numb.new.parse(165.chr+54.chr+48.chr+48.chr+46.chr+48.chr+48.chr+32.chr)
|
227
|
+
end
|
228
|
+
|
229
|
+
def test_rupee
|
230
|
+
expected = {:currency => 'INR', :value => 4000.0}
|
231
|
+
assert_equal expected, Numb.new.parse("Rs4,000")
|
232
|
+
assert_equal expected, Numb.new.parse(82.chr+115.chr+52.chr+44.chr+48.chr+48.chr+48.chr+46.chr+48.chr+48.chr+32.chr)
|
233
|
+
assert_equal expected, Numb.new.parse("INR4,000")
|
234
|
+
end
|
235
|
+
|
236
|
+
def test_singapore_dollar
|
237
|
+
expected = {:currency => 'SGD', :value => 5.48}
|
238
|
+
assert_equal expected, Numb.new(:require => :currency).parse("S$5.48")
|
239
|
+
end
|
240
|
+
|
241
|
+
def test_swedish_kroner
|
242
|
+
expected = {:currency => 'SEK', :value => 5.48}
|
243
|
+
assert_equal expected, Numb.new(:require => :currency).parse("SEK5.48")
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: trafficbroker-numb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- trafficbroker
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-05-15 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: technology@trafficbroker.co.uk
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.rdoc
|
25
|
+
files:
|
26
|
+
- LICENSE
|
27
|
+
- README.rdoc
|
28
|
+
- Rakefile
|
29
|
+
- VERSION.yml
|
30
|
+
- lib/numb.rb
|
31
|
+
- test/numb_test.rb
|
32
|
+
- test/test_helper.rb
|
33
|
+
has_rdoc: true
|
34
|
+
homepage: http://github.com/trafficbroker/numb
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options:
|
37
|
+
- --charset=UTF-8
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: "0"
|
45
|
+
version:
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: "0"
|
51
|
+
version:
|
52
|
+
requirements: []
|
53
|
+
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 1.2.0
|
56
|
+
signing_key:
|
57
|
+
specification_version: 2
|
58
|
+
summary: TODO
|
59
|
+
test_files:
|
60
|
+
- test/numb_test.rb
|
61
|
+
- test/test_helper.rb
|