latinum 0.2.0 → 0.2.3
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/README.md +77 -0
- data/lib/latinum.rb +9 -1
- data/lib/latinum/bank.rb +16 -10
- data/lib/latinum/collection.rb +3 -1
- data/lib/latinum/currencies/global.rb +13 -0
- data/lib/latinum/extensions/bigdecimal-1.8.rb +6 -0
- data/lib/latinum/formatters.rb +2 -2
- data/lib/latinum/resource.rb +11 -3
- data/lib/latinum/version.rb +1 -1
- data/test/test_bank.rb +21 -1
- data/test/test_collection.rb +27 -0
- metadata +4 -2
data/README.md
CHANGED
@@ -7,6 +7,83 @@ Latinum
|
|
7
7
|
|
8
8
|
Latinum is a framework for resource and currency calculations. *It is currently a work in progress and not designed to be taken seriously at this time*.
|
9
9
|
|
10
|
+
Basic Usage
|
11
|
+
-----------
|
12
|
+
|
13
|
+
Latinum has several core concepts:
|
14
|
+
|
15
|
+
- A `Resource` represents an immutable value with a specific face name (e.g. `'USD'`).
|
16
|
+
- A `Resource` can only be combined with resources with the same face name.
|
17
|
+
- A `Bank` is responsible for managing currencies and formatting options.
|
18
|
+
- A `Bank` can exchange currencies explicitly with a given set of exchange rates.
|
19
|
+
- A `Collection` is responsible for adding currencies together and is completely deterministic.
|
20
|
+
|
21
|
+
### Resources and Collections ###
|
22
|
+
|
23
|
+
To create a new resource, use a string for accuracy:
|
24
|
+
|
25
|
+
> ten = Latinum::Resource.new("10.00", "NZD")
|
26
|
+
=> 10.0 NZD
|
27
|
+
> ten.amount == "10.00".to_d
|
28
|
+
=> true
|
29
|
+
|
30
|
+
You can add resources of different values but with the same name:
|
31
|
+
|
32
|
+
> ten + ten
|
33
|
+
=> 20.0 NZD
|
34
|
+
|
35
|
+
But, you can't add resources of different names together:
|
36
|
+
|
37
|
+
> twenty = Latinum::Resource.new("20.00", "AUD")
|
38
|
+
=> 20.0 AUD
|
39
|
+
> ten + twenty
|
40
|
+
ArgumentError: Cannot operate on different currencies!
|
41
|
+
|
42
|
+
To add multiple currencies together, use a collection:
|
43
|
+
|
44
|
+
> currencies = Set.new
|
45
|
+
> collection = Latinum::Collection.new(currencies)
|
46
|
+
> collection << ten
|
47
|
+
> collection << twenty
|
48
|
+
> currencies.collect {|currency| collection[currency]}
|
49
|
+
=> [10.0 NZD, 20.0 AUD]
|
50
|
+
|
51
|
+
### Banks and Exchange Rates ###
|
52
|
+
|
53
|
+
The bank is responsible for formatting and exchange rates:
|
54
|
+
|
55
|
+
require 'latinum/bank'
|
56
|
+
require 'latinum/currencies/global'
|
57
|
+
|
58
|
+
> bank = Latinum::Bank.new(Latinum::Currencies::Global)
|
59
|
+
> bank << Latinum::ExchangeRate.new("NZD", "AUD", "0.5")
|
60
|
+
|
61
|
+
> nzd = Latinum::Resource.new("10", "NZD")
|
62
|
+
=> 10.0 NZD
|
63
|
+
> aud = bank.exchange nzd, "AUD"
|
64
|
+
=> 5.0 AUD
|
65
|
+
|
66
|
+
Formatting an amount is typically required for presentation to the end user:
|
67
|
+
|
68
|
+
> bank.format(nzd)
|
69
|
+
=> "$10.00 NZD"
|
70
|
+
|
71
|
+
> bank.format(aud, :format => :compact)
|
72
|
+
=> "$5.00"
|
73
|
+
|
74
|
+
The bank can also be used to parse currency, which will depend on the priority of currencies if a symbol that matches multiple currencies is supplied:
|
75
|
+
|
76
|
+
> bank.parse("$5")
|
77
|
+
=> 5.0 USD
|
78
|
+
|
79
|
+
> bank.parse("€5")
|
80
|
+
=> 5.0 EUR
|
81
|
+
|
82
|
+
Currency codes take priority over symbols if specified:
|
83
|
+
|
84
|
+
> bank.parse("€5 NZD")
|
85
|
+
=> 5.0 NZD
|
86
|
+
|
10
87
|
License
|
11
88
|
-------
|
12
89
|
|
data/lib/latinum.rb
CHANGED
@@ -18,5 +18,13 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
+
require 'latinum/bank'
|
21
22
|
require 'latinum/resource'
|
22
|
-
require 'latinum/collection'
|
23
|
+
require 'latinum/collection'
|
24
|
+
|
25
|
+
require 'bigdecimal'
|
26
|
+
require 'bigdecimal/util'
|
27
|
+
|
28
|
+
if RUBY_VERSION < "1.9"
|
29
|
+
require 'latinum/extensions/bigdecimal-1.8'
|
30
|
+
end
|
data/lib/latinum/bank.rb
CHANGED
@@ -25,7 +25,7 @@ module Latinum
|
|
25
25
|
def initialize(input, output, factor)
|
26
26
|
@input = input
|
27
27
|
@output = output
|
28
|
-
@factor =
|
28
|
+
@factor = factor.to_d
|
29
29
|
end
|
30
30
|
|
31
31
|
attr :input
|
@@ -38,6 +38,8 @@ module Latinum
|
|
38
38
|
@rates = []
|
39
39
|
@exchange = {}
|
40
40
|
|
41
|
+
# This implementation may change:
|
42
|
+
@currencies = {}
|
41
43
|
@formatters = {}
|
42
44
|
|
43
45
|
# Symbols and their associated priorities
|
@@ -52,8 +54,10 @@ module Latinum
|
|
52
54
|
resources.each do |name, config|
|
53
55
|
name = (config[:name] || name).to_s
|
54
56
|
|
57
|
+
@currencies[name] = config
|
58
|
+
|
55
59
|
# Create a formatter:
|
56
|
-
|
60
|
+
@formatters[name] = config[:formatter].new(config)
|
57
61
|
|
58
62
|
if config[:symbol]
|
59
63
|
symbols = (@symbols[config[:symbol]] ||= [])
|
@@ -63,30 +67,32 @@ module Latinum
|
|
63
67
|
end
|
64
68
|
end
|
65
69
|
|
70
|
+
def [] name
|
71
|
+
@currencies[name]
|
72
|
+
end
|
73
|
+
|
66
74
|
attr :rates
|
67
75
|
attr :symbols
|
68
|
-
attr :
|
76
|
+
attr :currencies
|
69
77
|
|
70
|
-
def <<
|
78
|
+
def << rate
|
71
79
|
@rates << rate
|
72
80
|
|
73
81
|
@exchange[rate.input] ||= {}
|
74
82
|
@exchange[rate.input][rate.output] = rate
|
75
83
|
end
|
76
84
|
|
77
|
-
def []= name, formatter
|
78
|
-
@formatters[name] = formatter
|
79
|
-
end
|
80
|
-
|
81
85
|
def exchange(resource, for_name)
|
82
86
|
rate = @exchange[resource.name][for_name]
|
83
87
|
raise ArgumentError.new("Invalid rate specified #{rate}") if rate == nil
|
84
88
|
|
85
|
-
|
89
|
+
config = self[for_name]
|
90
|
+
|
91
|
+
resource.exchange(rate.factor, for_name, config[:precision])
|
86
92
|
end
|
87
93
|
|
88
94
|
def parse(string)
|
89
|
-
parts = string.strip.split(/\s
|
95
|
+
parts = string.strip.split(/\s+/, 2)
|
90
96
|
|
91
97
|
if parts.size == 2
|
92
98
|
Resource.new(parts[0].gsub(/[^\.0-9]/, ''), parts[1])
|
data/lib/latinum/collection.rb
CHANGED
@@ -25,7 +25,7 @@ module Latinum
|
|
25
25
|
class Collection
|
26
26
|
def initialize(names = Set.new)
|
27
27
|
@names = names
|
28
|
-
@resources = Hash.new {|hash, key| @names << key; BigDecimal.new(0)}
|
28
|
+
@resources = Hash.new {|hash, key| @names << key; BigDecimal.new("0")}
|
29
29
|
end
|
30
30
|
|
31
31
|
attr :names
|
@@ -33,6 +33,8 @@ module Latinum
|
|
33
33
|
|
34
34
|
def << resource
|
35
35
|
@resources[resource.name] += resource.amount
|
36
|
+
|
37
|
+
return self
|
36
38
|
end
|
37
39
|
|
38
40
|
def [] key
|
@@ -27,6 +27,7 @@ module Latinum
|
|
27
27
|
Global = {}
|
28
28
|
|
29
29
|
Global[:NZD] = {
|
30
|
+
:precision => 2,
|
30
31
|
:symbol => '$',
|
31
32
|
:name => 'NZD',
|
32
33
|
:description => 'New Zealand Dollar',
|
@@ -34,6 +35,7 @@ module Latinum
|
|
34
35
|
}
|
35
36
|
|
36
37
|
Global[:GBP] = {
|
38
|
+
:precision => 2,
|
37
39
|
:symbol => '£',
|
38
40
|
:name => 'GBP',
|
39
41
|
:description => 'Pound Sterling',
|
@@ -41,6 +43,7 @@ module Latinum
|
|
41
43
|
}
|
42
44
|
|
43
45
|
Global[:AUD] = {
|
46
|
+
:precision => 2,
|
44
47
|
:symbol => '$',
|
45
48
|
:name => 'AUD',
|
46
49
|
:description => 'Australian Dollar',
|
@@ -48,6 +51,7 @@ module Latinum
|
|
48
51
|
}
|
49
52
|
|
50
53
|
Global[:USD] = {
|
54
|
+
:precision => 2,
|
51
55
|
:symbol => '$',
|
52
56
|
:name => 'USD',
|
53
57
|
:description => 'United States Dollar',
|
@@ -55,6 +59,7 @@ module Latinum
|
|
55
59
|
}
|
56
60
|
|
57
61
|
Global[:EUR] = {
|
62
|
+
:precision => 2,
|
58
63
|
:symbol => '€',
|
59
64
|
:name => 'EUR',
|
60
65
|
:description => 'Euro',
|
@@ -62,5 +67,13 @@ module Latinum
|
|
62
67
|
#:delimeter => '.',
|
63
68
|
#:separator => ','
|
64
69
|
}
|
70
|
+
|
71
|
+
Global[:JPY] = {
|
72
|
+
:precision => 0,
|
73
|
+
:symbol => '¥',
|
74
|
+
:name => 'JPY',
|
75
|
+
:description => 'Japanese Yen',
|
76
|
+
:formatter => Formatters::DecimalCurrencyFormatter
|
77
|
+
}
|
65
78
|
end
|
66
79
|
end
|
data/lib/latinum/formatters.rb
CHANGED
@@ -39,14 +39,14 @@ module Latinum
|
|
39
39
|
@symbol = options[:symbol] || '$'
|
40
40
|
@separator = options[:separator] || '.'
|
41
41
|
@delimeter = options[:delimter] || ','
|
42
|
-
@places = options[:
|
42
|
+
@places = options[:precision] || 2
|
43
43
|
@zero = options[:zero] || '0'
|
44
44
|
|
45
45
|
@name = options[:name]
|
46
46
|
end
|
47
47
|
|
48
48
|
def format(amount, options = DEFAULT_OPTIONS)
|
49
|
-
fix, frac = amount.to_s('F').split(/\./, 2)
|
49
|
+
fix, frac = amount.abs.to_s('F').split(/\./, 2)
|
50
50
|
|
51
51
|
# The sign of the number
|
52
52
|
sign = amount.sign < 0 ? '-' : ''
|
data/lib/latinum/resource.rb
CHANGED
@@ -29,19 +29,19 @@ module Latinum
|
|
29
29
|
attr :name
|
30
30
|
|
31
31
|
def initialize(amount, name)
|
32
|
-
@amount =
|
32
|
+
@amount = amount.to_d
|
33
33
|
@name = name
|
34
34
|
end
|
35
35
|
|
36
36
|
# By default, we can only add and subtract if the name is the same
|
37
37
|
def + other
|
38
|
-
|
38
|
+
raise ArgumentError.new("Cannot operate on different currencies!") if @name != other.name
|
39
39
|
|
40
40
|
self.class.new(@amount + other.amount, @name)
|
41
41
|
end
|
42
42
|
|
43
43
|
def - other
|
44
|
-
|
44
|
+
raise ArgumentError.new("Cannot operate on different currencies!") if @name != other.name
|
45
45
|
|
46
46
|
self.class.new(@amount - other.amount, @name)
|
47
47
|
end
|
@@ -54,6 +54,14 @@ module Latinum
|
|
54
54
|
self.class.new(@amount * factor, @name)
|
55
55
|
end
|
56
56
|
|
57
|
+
def exchange(rate, name, precision = nil)
|
58
|
+
exchanged_amount = @amount * rate
|
59
|
+
|
60
|
+
exchanged_amount = exchanged_amount.round(precision) if precision
|
61
|
+
|
62
|
+
self.class.new(exchanged_amount, name)
|
63
|
+
end
|
64
|
+
|
57
65
|
def to_s(options = {})
|
58
66
|
@amount.to_s('F') + ' ' + @name.to_s
|
59
67
|
end
|
data/lib/latinum/version.rb
CHANGED
data/test/test_bank.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
|
2
2
|
require 'helper'
|
3
3
|
|
4
|
-
require 'latinum
|
4
|
+
require 'latinum'
|
5
5
|
require 'latinum/currencies/global'
|
6
6
|
|
7
7
|
class BankTest < Test::Unit::TestCase
|
8
8
|
def setup
|
9
9
|
@bank = Latinum::Bank.new
|
10
10
|
@bank.import(Latinum::Currencies::Global)
|
11
|
+
|
12
|
+
@bank << Latinum::ExchangeRate.new("NZD", "AUD", "0.5")
|
11
13
|
end
|
12
14
|
|
13
15
|
def test_formatting
|
@@ -17,5 +19,23 @@ class BankTest < Test::Unit::TestCase
|
|
17
19
|
|
18
20
|
resource = Latinum::Resource.new("391", "AUD")
|
19
21
|
assert_equal "$391.00 AUD", @bank.format(resource)
|
22
|
+
|
23
|
+
resource = Latinum::Resource.new("-100", "NZD")
|
24
|
+
assert_equal "-$100.00 NZD", @bank.format(resource)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_exchange
|
28
|
+
nzd = Latinum::Resource.new("10", "NZD")
|
29
|
+
|
30
|
+
aud = @bank.exchange nzd, "AUD"
|
31
|
+
assert_equal Latinum::Resource.new("5", "AUD"), aud
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_parsing
|
35
|
+
assert_equal Latinum::Resource.new("5", "USD"), @bank.parse("$5")
|
36
|
+
assert_equal Latinum::Resource.new("5", "NZD"), @bank.parse("$5 NZD")
|
37
|
+
assert_equal Latinum::Resource.new("5", "EUR"), @bank.parse("€5")
|
38
|
+
|
39
|
+
assert_equal Latinum::Resource.new("5", "NZD"), @bank.parse("5 NZD")
|
20
40
|
end
|
21
41
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
require 'latinum'
|
5
|
+
require 'latinum/currencies/global'
|
6
|
+
|
7
|
+
require 'set'
|
8
|
+
|
9
|
+
class CollectionTest < Test::Unit::TestCase
|
10
|
+
def setup
|
11
|
+
@bank = Latinum::Bank.new
|
12
|
+
@bank.import(Latinum::Currencies::Global)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_collections
|
16
|
+
resource = Latinum::Resource.new("10", "NZD")
|
17
|
+
|
18
|
+
currencies = Set.new
|
19
|
+
collection = Latinum::Collection.new(currencies)
|
20
|
+
|
21
|
+
collection << resource
|
22
|
+
assert_equal resource, collection["NZD"]
|
23
|
+
|
24
|
+
collection << resource
|
25
|
+
assert_equal resource * 2, collection["NZD"]
|
26
|
+
end
|
27
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: latinum
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-27 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description:
|
15
15
|
email: samuel.williams@oriontransfer.co.nz
|
@@ -20,12 +20,14 @@ files:
|
|
20
20
|
- lib/latinum/bank.rb
|
21
21
|
- lib/latinum/collection.rb
|
22
22
|
- lib/latinum/currencies/global.rb
|
23
|
+
- lib/latinum/extensions/bigdecimal-1.8.rb
|
23
24
|
- lib/latinum/formatters.rb
|
24
25
|
- lib/latinum/resource.rb
|
25
26
|
- lib/latinum/version.rb
|
26
27
|
- lib/latinum.rb
|
27
28
|
- test/helper.rb
|
28
29
|
- test/test_bank.rb
|
30
|
+
- test/test_collection.rb
|
29
31
|
- README.md
|
30
32
|
homepage: http://www.oriontransfer.co.nz/gems/latinum
|
31
33
|
licenses: []
|