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 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&nbsp;") # => {: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
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 2
3
+ :patch: 0
4
+ :major: 0
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&#xA0;' => 'DKK',
135
+
136
+ 'EUR' => 'EUR',
137
+ '€' => 'EUR',
138
+ 194.chr+128.chr => "EUR",
139
+ '&euro;' => 'EUR',
140
+ '&#8364;' => 'EUR',
141
+
142
+ 'GBP' => 'GBP',
143
+ '\243' => 'GBP',
144
+ '£' => 'GBP',
145
+ '&#xA3;' => 'GBP',
146
+ 'UK' => "GBP",
147
+ 'UK\243' => "GBP",
148
+ 'UK£' => "GBP",
149
+ 'UK'+239.chr+189.chr+163.chr => "GBP",
150
+ '&pound;' => 'GBP',
151
+ '&#163;' => 'GBP',
152
+
153
+ 'Rs' => 'INR',
154
+ 'INR' => 'INR',
155
+
156
+ 239.chr+189.chr+165.chr => 'JPY',
157
+ '¥' => 'JPY',
158
+ '&yen;' => 'JPY',
159
+ '&#165;' => '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
+ '&#1547;' => 'AFN',
326
+ '&#402;' => 'AWG',
327
+ '&#1084;&#1072;&#1085;' => 'AZN',
328
+ '&#1083;&#1074;' => 'BGN',
329
+ '&#6107;' => 'KHR',
330
+ '&#8353;' => 'CRC',
331
+ '&#8369;' => 'CUP',
332
+ '&#75;&#269;' => 'CZK',
333
+ '&#8360;' => 'INR',
334
+ '&#65020;' => 'IRR',
335
+ '&#8362;' => 'ILS',
336
+ '&#1083;&#1074;' => 'KZT',
337
+ '&#8361;' => 'KPW',
338
+ '&#8361;' => 'KRW',
339
+ '&#1083;&#1074;' => 'KGS',
340
+ '&#8365;' => 'LAK',
341
+ '&#1076;&#1077;&#1085;' => 'MKD',
342
+ '&#8360;' => 'MUR',
343
+ '&#8366;' => 'MNT',
344
+ '&#8360;' => 'NPR',
345
+ '&#8358;' => 'NGN',
346
+ '&#8361;' => 'KPW',
347
+ '&#65020;' => 'OMR',
348
+ '&#8360;' => 'PKR',
349
+ '&#122;&#322;' => 'PLN',
350
+ '&#65020;' => 'QAR',
351
+ '&#1088;&#1091;&#1073;' => 'RUB',
352
+ '&#65020;' => 'SAR',
353
+ '&#1044;&#1080;&#1085;&#46;' => 'RSD',
354
+ '&#8360;' => 'SCR',
355
+ '&#8361;' => 'KRW',
356
+ '&#8360;' => 'LKR',
357
+ '&#3647;' => 'THB',
358
+ '&#8356;' => 'TRL',
359
+ '&#8372;' => 'UAH',
360
+ '&#1083;&#1074;' => 'UZS',
361
+ '&#8363;' => 'VND',
362
+ '&#65020;' => '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
+ '&#402;' => '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&nbsp;")
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('&#1088;&#1091;&#1073;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&#xA0;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("&#xA3;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
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ require 'numb'
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